/**
 * 2021-05新版本
 * 更改CBC算法漏洞
 * 查找this.pkcs7padding(onePlain,1)
 */

/**
 * 
 * sm2算法
 * 使用方式如下：
 * SG_sm2generateKeyPair()
 * SG_sm2Encrypt(D,C)
 * SG_sm2Decrypt(B,D)
 * 
 * sm3算法
 * 使用方式如下：
 * SG_sm3encrypt(E)
 * 
 * sm4-ecb算法
 * 使用方式如下：
 * generateSM4Key()
 * SG_sm4encrypt(D,A)
 * SG_sm4decrypt(B,A)
 * 
 */
 var charSet = function () {
    this.parseUTF8 = function (B) {
      for (var B = unescape(encodeURIComponent(B)), C = B.length, A = [], D = 0; D < C; D++) {
        A[D >>> 2] |= (B.charCodeAt(D) & 255) << 24 - D % 4 * 8
      }
      return new WordArray(A, C)
    };
    this.stringifyUTF8 = function (F) {
      try {
        for (var A = decodeURIComponent, G = escape, E, B = F.words, H = F.sigBytes, F = [], D = 0; D < H; D++) {
          var I = B[D >>> 2] >>> 24 - D % 4 * 8 & 255;
          I != 0 && F.push(String.fromCharCode(I))
        }
        E = F.join("");
        console.log(E,'eeee')
        console.log(G(E).replace(/%/g, '%25'),'eesaaeas')
        return A(G(E))
      } catch (C) {
        console.log(C,'错误异常')
        throw Error("Malformed UTF-8 data")
      }
    };
    this.HexParse = function (B) {
      for (var C = B.length, A = [], D = 0; D < C; D += 2) {
        A[D >>> 3] |= parseInt(B.substr(D, 2), 16) << 24 - D % 8 * 4
      }
      return new WordArray(A, C / 2)
    };
    this.HexStringify = function (C) {
      for (var B = C.words, C = C.sigBytes, D = [], E = 0; E < C; E++) {
        var A = B[E >>> 2] >>> 24 - E % 4 * 8 & 255;
        D.push((A >>> 4).toString(16));
        D.push((A & 15).toString(16))
      }
      return D.join("")
    };
    return this
  },
  WordArray = function (B, A) {
    this.words = B || [];
    this.sigBytes = A != void 0 ? A : B.length * 4;
    this.getArrs = function () {
      return this.words
    };
    return this
  },
  dbits, canary = 244837814094590,
  j_lm = (canary & 16777215) == 15715070;
var BI_FP = 52;
var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz",
  BI_RC = [],
  rr, vv;
rr = "0".charCodeAt(0);
for (vv = 0; vv <= 9; ++vv) {
  BI_RC[rr++] = vv
}
rr = "a".charCodeAt(0);
for (vv = 10; vv < 36; ++vv) {
  BI_RC[rr++] = vv
}
rr = "A".charCodeAt(0);
for (vv = 10; vv < 36; ++vv) {
  BI_RC[rr++] = vv
}

function int2char(A) {
  return BI_RM.charAt(A)
}

function intAt(A, B) {
  var C = BI_RC[A.charCodeAt(B)];
  return C == null ? -1 : C
}

function IEVersion() {
  var C = navigator.userAgent;
  var F = C.indexOf("compatible") > -1 && C.indexOf("MSIE") > -1;
  var A = C.indexOf("Edge") > -1 && !F;
  var B = C.indexOf("Trident") > -1 && C.indexOf("rv:11.0") > -1;
  if (F) {
    var E = new RegExp("MSIE (\\d+\\.\\d+);");
    E.test(C);
    var D = parseFloat(RegExp["$1"]);
    if (D == 7) {
      return 7
    } else {
      if (D == 8) {
        return 8
      } else {
        if (D == 9) {
          return 9
        } else {
          if (D == 10) {
            return 10
          } else {
            return 6
          }
        }
      }
    }
  } else {
    if (A) {
      return "edge"
    } else {
      if (B) {
        return 11
      } else {
        return -1
      }
    }
  }
}

function myBrowser() {
  var D = navigator.userAgent;
  var F = D.indexOf("Opera") > -1;
  var B = D.indexOf("compatible") > -1 && D.indexOf("MSIE") > -1;
  var E = D.indexOf("Edge") > -1 && !B;
  var C = D.indexOf("Trident") > -1 && D.indexOf("rv:11.0") > -1;
  var H = D.indexOf("Firefox") > -1;
  var A = D.indexOf("Safari") > -1;
  var G = D.indexOf("Chrome") > -1;
  if (E) {
    return "edge"
  }
  if (C) {
    return "IE11"
  }
  if (H) {
    return "FF"
  }
  if (G) {
    return "FF"
  }
}
var SecureRandom = function () {
    function G(J) {
      D[F++] ^= J & 255;
      D[F++] ^= J >> 8 & 255;
      D[F++] ^= J >> 16 & 255;
      D[F++] ^= J >> 24 & 255;
      F >= A && (F -= A)
    }
    var I, D, F, A = 256;
    if (D == null) {
      D = [];
      F = 0;
      var E;
      for (; F < A;) {
        E = Math.floor(window.crypto.getRandomValues(new Uint16Array(1))[0]), D[F++] = E >>> 8, D[F++] = E & 255
      }
      if (myBrowser() == "FF" && window.crypto) {
        var C = new ArrayBuffer(32);
        var H = new Int8Array(C);
        window.crypto.getRandomValues(H);
        for (E = 0; E < H.length; ++E) {
          D[E] = H[E] & 255
        }
      } else {
        if (myBrowser() == "IE11") {
          var C = new ArrayBuffer(32);
          var H = new Int8Array(C);
          var B = window.crypto || window.msCrypto;
          B.getRandomValues(H);
          for (E = 0; E < H.length; ++E) {
            D[E] = H[E] & 255
          }
        } else {
          if (myBrowser() == "edge") {
            var C = new ArrayBuffer(32);
            var H = new Int8Array(C);
            var B = window.crypto || window.msCrypto;
            B.getRandomValues(H);
            for (E = 0; E < H.length; ++E) {
              D[E] = H[E] & 255
            }
          } else {}
        }
      }
      F = 0;
      G((new Date).getTime())
    }
    this.nextBytes = function (L) {
      for (var N = 0; N < L.length; ++N) {
        var J = L,
          K = N,
          M;
        if (I == null) {
          G((new Date).getTime());
          I = new prng_newstate;
          I.init(D);
          for (F = 0; F < D.length; ++F) {
            D[F] = 0
          }
          F = 0
        }
        M = I.next();
        J[K] = M
      }
    }
  },
  prng_newstate = function () {
    this.j = this.i = 0;
    this.S = [];
    this.init = function (A) {
      for (var B, C, D = 0; D < 256; ++D) {
        this.S[D] = D
      }
      for (D = B = 0; D < 256; ++D) {
        B = B + this.S[D] + A[D % A.length] & 255, C = this.S[D], this.S[D] = this.S[B], this.S[B] = C
      }
      this.j = this.i = 0
    };
    this.next = function () {
      var A;
      this.i = this.i + 1 & 255;
      this.j = this.j + this.S[this.i] & 255;
      A = this.S[this.i];
      this.S[this.i] = this.S[this.j];
      this.S[this.j] = A;
      return this.S[A + this.S[this.i] & 255]
    }
  },
  ECFieldElementFp = function (B, A) {
    this.x = A;
    this.q = B
  };

function parseBigInt(B, A) {
  return new BigInteger(B, A)
}

function linebrk(B, C) {
  for (var A = "", D = 0; D + C < B.length;) {
    A += B.substring(D, D + C), D += C
  }
  return A + B.substring(D, B.length)
}

function byte2Hex(A) {
  return A < 16 ? "0" + A.toString(16) : A.toString(16)
}

function pkcs1pad2(B, C) {
  for (var D = [], A = B.length - 1; A >= 0 && C > 0;) {
    var E = B.charCodeAt(A--);
    E < 128 ? (D[--C] = E) : E > 127 && E < 2048 ? (D[--C] = E & 63 | 128, D[--C] = E >> 6 | 192) : (D[--C] = E & 63 | 128, D[--C] = E >> 6 & 63 | 128, D[--C] = E >> 12 | 224)
  }
  D[--C] = 0;
  A = new SecureRandom;
  for (E = []; C > 2;) {
    for (E[0] = 0; E[0] == 0;) {
      A.nextBytes(E)
    }
    D[--C] = E[0]
  }
  D[--C] = 2;
  D[--C] = 0;
  return new BigInteger(D)
}

function pkcs1unpad2(B, F) {
  for (var C = B.toByteArray(), E = 0; E < C.length && C[E] == 0;) {
    ++E
  }
  if (C.length - E != F - 1 || C[E] != 2) {
    return null
  }
  for (++E; C[E] != 0;) {
    if (++E >= C.length) {
      return null
    }
  }
  for (var A = ""; ++E < C.length;) {
    var D = C[E] & 255;
    D < 128 ? (A += String.fromCharCode(D)) : D > 191 && D < 224 ? (A += String.fromCharCode((D & 31) << 6 | C[E + 1] & 63), ++E) : (A += String.fromCharCode((D & 15) << 12 | (C[E + 1] & 63) << 6 | C[E + 2] & 63), E += 2)
  }
  return A
}
Array.Clear = function (A) {
  for (elm in A) {
    A[elm] = null
  }
};
Array.Copy = function (C, E, A, D, B) {
  C = C.slice(E, E + B);
  for (E = 0; E < C.length; E++) {
    A[D] = C[E], D++
  }
};
window.Int32 = {
  minValue: -parseInt("10000000000000000000000000000000", 2),
  maxValue: parseInt("1111111111111111111111111111111", 2),
  parse: function (D) {
    if (D < this.minValue) {
      for (var D = new Number(-D), D = D.toString(2), D = D.substr(D.length - 31, 31), C = "", B = 0; B < D.length; B++) {
        var A = D.substr(B, 1);
        C += A == "0" ? "1" : "0"
      }
      D = parseInt(C, 2);
      return D + 1
    } else {
      if (D > this.maxValue) {
        D = Number(D).toString(2);
        D = D.substr(D.length - 31, 31);
        C = "";
        for (B = 0; B < D.length; B++) {
          A = D.substr(B, 1), C += A == "0" ? "1" : "0"
        }
        D = parseInt(C, 2);
        return -(D + 1)
      } else {
        return D
      }
    }
  },
  parseByte: function (D) {
    if (D < 0) {
      for (var D = new Number(-D), D = D.toString(2), D = D.substr(D.length - 8, 8), C = "", B = 0; B < D.length; B++) {
        var A = D.substr(B, 1);
        C += A == "0" ? "1" : "0"
      }
      return parseInt(C, 2) + 1
    } else {
      return D > 255 ? (D = Number(D).toString(2), parseInt(D.substr(D.length - 8, 8), 2)) : D
    }
  }
};
if (typeof KJUR == "undefined" || !KJUR) {
  KJUR = {}
}
if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) {
  KJUR.crypto = {}
}
if (typeof KJUR == "undefined" || !KJUR) {
  KJUR = {}
}
if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) {
  KJUR.crypto = {}
}
var SboxTable = [
    [214, 144, 233, 254, 204, 225, 61, 183, 22, 182, 20, 194, 40, 251, 44, 5],
    [43, 103, 154, 118, 42, 190, 4, 195, 170, 68, 19, 38, 73, 134, 6, 153],
    [156, 66, 80, 244, 145, 239, 152, 122, 51, 84, 11, 67, 237, 207, 172, 98],
    [228, 179, 28, 169, 201, 8, 232, 149, 128, 223, 148, 250, 117, 143, 63, 166],
    [71, 7, 167, 252, 243, 115, 23, 186, 131, 89, 60, 25, 230, 133, 79, 168],
    [104, 107, 129, 178, 113, 100, 218, 139, 248, 235, 15, 75, 112, 86, 157, 53],
    [30, 36, 14, 94, 99, 88, 209, 162, 37, 34, 124, 59, 1, 33, 120, 135],
    [212, 0, 70, 87, 159, 211, 39, 82, 76, 54, 2, 231, 160, 196, 200, 158],
    [234, 191, 138, 210, 64, 199, 56, 181, 163, 247, 242, 206, 249, 97, 21, 161],
    [224, 174, 93, 164, 155, 52, 26, 85, 173, 147, 50, 48, 245, 140, 177, 227],
    [29, 246, 226, 46, 130, 102, 202, 96, 192, 41, 35, 171, 13, 83, 78, 111],
    [213, 219, 55, 69, 222, 253, 142, 47, 3, 255, 106, 114, 109, 108, 91, 81],
    [141, 27, 175, 146, 187, 221, 188, 127, 17, 217, 92, 65, 31, 16, 90, 216],
    [10, 193, 49, 136, 165, 205, 123, 189, 45, 116, 208, 18, 184, 229, 180, 176],
    [137, 105, 151, 74, 12, 150, 119, 126, 101, 185, 241, 9, 197, 110, 198, 132],
    [24, 240, 125, 236, 58, 220, 77, 32, 121, 238, 95, 62, 215, 203, 57, 72]
  ],
  CK = [462357, 472066609, 943670861, 1415275113, 1886879365, 2358483617, 2830087869, 3301692121, 3773296373, 4228057617, 404694573, 876298825, 1347903077, 1819507329, 2291111581, 2762715833, 3234320085, 3705924337, 4177462797, 337322537, 808926789, 1280531041, 1752135293, 2223739545, 2695343797, 3166948049, 3638552301, 4110090761, 269950501, 741554753, 1213159005, 1684763257],
  FK = [2746333894, 1453994832, 1736282519, 2993693404];

function bigxor(B, A) {
  return B ^ A
}

function leftshift(A, B) {
  B %= 32;
  return A << B | A >>> 32 - B
}

function prefixInteger(A, B) {
  return Array(B + 1).join("0").split("").concat(String(A).split("")).slice(-B).join("")
}

function sm4Sbox(A) {
  return SboxTable[(A & 4026531840) >>> 28][(A & 251658240) >>> 24] << 24 | SboxTable[(A & 15728640) >>> 20][(A & 983040) >>> 16] << 16 | SboxTable[(A & 61440) >>> 12][(A & 3840) >>> 8] << 8 | SboxTable[(A & 240) >>> 4][(A & 15) >>> 0] << 0
}

function GET_ULONG_BE(A) {
  A = sm4Sbox(A);
  return bigxor(bigxor(bigxor(A, leftshift(A, 2)), bigxor(leftshift(A, 10), leftshift(A, 18))), leftshift(A, 24))
}

function PUT_ULONG_BE(A) {
  A = sm4Sbox(A);
  return bigxor(A, bigxor(leftshift(A, 13), leftshift(A, 23)))
}

function sm4_getkey(C) {
  var A = [],
    B = [];
  A[0] = bigxor(C[0], FK[0]);
  A[1] = bigxor(C[1], FK[1]);
  A[2] = bigxor(C[2], FK[2]);
  A[3] = bigxor(C[3], FK[3]);
  for (C = 0; C < 32; C++) {
    A[C + 4] = bigxor(A[C], PUT_ULONG_BE(bigxor(bigxor(A[C + 1], A[C + 2]), bigxor(A[C + 3], CK[C])))), B[C] = A[C + 4].toString(16)
  }
  return B
}

function KJUR_encrypt_sm4(A, F) {
  for (var G = Math.ceil(A.length / 4), H = [], D = 0; D < G; D++) {
    for (var E = A.slice(D * 4, (D + 1) * 4), B = sm4_getkey(F), C = 0; C < 32; C++) {
      E[C + 4] = bigxor(E[C], GET_ULONG_BE(bigxor(bigxor(E[C + 1], E[C + 2]), bigxor(E[C + 3], parseInt(B[C], 16)))))
    }
    H = H.concat([E[35].toString(10), E[34].toString(10), E[33].toString(10), E[32].toString(10)])
  }
  return new WordArray(H)
}

function KJUR_decrypt_sm4(G, B) {
  for (var C = Math.ceil(G.length / 4), I = [], E = 0; E < C; E++) {
    for (var D = G.slice(E * 4, (E + 1) * 4), A = sm4_getkey(B), H = [], F = A.length - 1; F >= 0; F--) {
      H[A.length - 1 - F] = A[F]
    }
    for (F = 0; F < 32; F++) {
      D[F + 4] = bigxor(D[F], GET_ULONG_BE(bigxor(bigxor(D[F + 1], D[F + 2]), bigxor(D[F + 3], parseInt(H[F], 16)))))
    }
    I = I.concat([D[35].toString(10), D[34].toString(10), D[33].toString(10), D[32].toString(10)])
  }
  return new WordArray(I)
}

function SG_sm4encrypt(D, A) {
  if (D == undefined || A == undefined) {
    return undefined
  }
  if (D == "" || A == "") {
    return undefined
  }
  var C = new charSet,
    B = KJUR_encrypt_sm4(C.parseUTF8(D).getArrs(), C.HexParse(A).getArrs());
  return C.HexStringify(B)
}

function SG_sm4decrypt(B, A) {
  console.log('a',A,'b',B,'加密数据')
  if (B == undefined || A == undefined) {
    return undefined
  }
  if (B == "" || A == "") {
    return undefined
  }
  var D = new charSet,
    C = D.HexParse(B),
    D = D.HexParse(A),
    C = KJUR_decrypt_sm4(C.getArrs(), D.getArrs());
    console.log(C,'c')
    console.log((new charSet).stringifyUTF8(C),'解析数据++++++++++++++')
  // return (new charSet).stringifyUTF8(C)
}

function encryptbyMD5(A) {
  return (new md5Obj).encryptbymd5(A)
}

function encryptbyBASE64(A) {
  return (new base64Obj).encryptbybase64(A)
}

function decryptbyBASE64(A) {
  return (new base64Obj).decryptbybase64(A)
}
var CryptoJS = CryptoJS || (function (J, A) {
  var E = {};
  var K = E.lib = {};
  var N = K.Base = (function () {
    function C() {}
    return {
      extend: function (P) {
        C.prototype = this;
        var O = new C();
        if (P) {
          O.mixIn(P)
        }
        if (!O.hasOwnProperty("init")) {
          O.init = function () {
            O.$super.init.apply(this, arguments)
          }
        }
        O.init.prototype = O;
        O.$super = this;
        return O
      },
      create: function () {
        var O = this.extend();
        O.init.apply(O, arguments);
        return O
      },
      init: function () {},
      mixIn: function (P) {
        for (var O in P) {
          if (P.hasOwnProperty(O)) {
            this[O] = P[O]
          }
        }
        if (P.hasOwnProperty("toString")) {
          this.toString = P.toString
        }
      },
      clone: function () {
        return this.init.prototype.extend(this)
      }
    }
  }());
  var B = K.WordArray = N.extend({
    init: function (C, O) {
      C = this.words = C || [];
      if (O != A) {
        this.sigBytes = O
      } else {
        this.sigBytes = C.length * 4
      }
    },
    toString: function (C) {
      return (C || D).stringify(this)
    },
    concat: function (R) {
      var P = this.words;
      var T = R.words;
      var C = this.sigBytes;
      var S = R.sigBytes;
      this.clamp();
      if (C % 4) {
        for (var O = 0; O < S; O += 1) {
          var Q = (T[O >>> 2] >>> (24 - (O % 4) * 8)) & 255;
          P[(C + O) >>> 2] |= Q << (24 - ((C + O) % 4) * 8)
        }
      } else {
        if (T.length > 65535) {
          for (var O = 0; O < S; O += 4) {
            P[(C + O) >>> 2] = T[O >>> 2]
          }
        } else {
          P.push.apply(P, T)
        }
      }
      this.sigBytes += S;
      return this
    },
    clamp: function () {
      var C = this.words;
      var O = this.sigBytes;
      C[O >>> 2] &= 4294967295 << (32 - (O % 4) * 8);
      C.length = J.ceil(O / 4)
    },
    clone: function () {
      var C = N.clone.call(this);
      C.words = this.words.slice(0);
      return C
    },
    random: function (P) {
      var C = [];
      for (var O = 0; O < P; O += 4) {
        C.push((J.random() * 4294967296) | 0)
      }
      return new B.init(C, P)
    }
  });
  var I = E.enc = {};
  var D = I.Hex = {
    stringify: function (P) {
      var C = P.words;
      var S = P.sigBytes;
      var Q = [];
      for (var O = 0; O < S; O += 1) {
        var R = (C[O >>> 2] >>> (24 - (O % 4) * 8)) & 255;
        Q.push((R >>> 4).toString(16));
        Q.push((R & 15).toString(16))
      }
      return Q.join("")
    },
    parse: function (P) {
      var Q = P.length;
      var C = [];
      for (var O = 0; O < Q; O += 2) {
        C[O >>> 3] |= parseInt(P.substr(O, 2), 16) << (24 - (O % 8) * 4)
      }
      return new B.init(C, Q / 2)
    }
  };
  var M = I.Latin1 = {
    stringify: function (P) {
      var C = P.words;
      var S = P.sigBytes;
      var Q = [];
      for (var O = 0; O < S; O += 1) {
        var R = (C[O >>> 2] >>> (24 - (O % 4) * 8)) & 255;
        Q.push(String.fromCharCode(R))
      }
      return Q.join("")
    },
    parse: function (O) {
      var Q = O.length;
      var C = [];
      for (var P = 0; P < Q; P += 1) {
        C[P >>> 2] |= (O.charCodeAt(P) & 255) << (24 - (P % 4) * 8)
      }
      return new B.init(C, Q)
    }
  };
  var G = I.Utf8 = {
    stringify: function (O) {
      try {
        return decodeURIComponent(escape(M.stringify(O)))
      } catch (C) {
        throw new Error("Malformed UTF-8 data")
      }
    },
    parse: function (C) {
      return M.parse(unescape(encodeURIComponent(C)))
    }
  };
  var L = K.BufferedBlockAlgorithm = N.extend({
    reset: function () {
      this._data = new B.init();
      this._nDataBytes = 0
    },
    _append: function (C) {
      if (typeof C == "string") {
        C = G.parse(C)
      }
      this._data.concat(C);
      this._nDataBytes += C.sigBytes
    },
    _process: function (O) {
      var Q = this._data;
      var C = Q.words;
      var S = Q.sigBytes;
      var R = this.blockSize;
      var V = R * 4;
      var W = S / V;
      if (O) {
        W = J.ceil(W)
      } else {
        W = J.max((W | 0) - this._minBufferSize, 0)
      }
      var U = W * R;
      var T = J.min(U * 4, S);
      if (U) {
        for (var P = 0; P < U; P += R) {
          this._doProcessBlock(C, P)
        }
        var X = C.splice(0, U);
        Q.sigBytes -= T
      }
      return new B.init(X, T)
    },
    clone: function () {
      var C = N.clone.call(this);
      C._data = this._data.clone();
      return C
    },
    _minBufferSize: 0
  });
  var F = K.Hasher = L.extend({
    cfg: N.extend(),
    init: function (C) {
      this.cfg = this.cfg.extend(C);
      this.reset()
    },
    reset: function () {
      L.reset.call(this);
      this._doReset()
    },
    update: function (C) {
      this._append(C);
      this._process();
      return this
    },
    finalize: function (C) {
      if (C) {
        this._append(C)
      }
      var O = this._doFinalize();
      return O
    },
    blockSize: 512 / 32,
    _createHelper: function (C) {
      return function (P, O) {
        return new C.init(O).finalize(P)
      }
    },
    _createHmacHelper: function (C) {
      return function (P, O) {
        return new H.HMAC.init(C, O).finalize(P)
      }
    }
  });
  var H = E.algo = {};
  return E
}(Math));
var dbits;
var canary = 244837814094590;
var j_lm = ((canary & 16777215) == 15715070);

function BigInteger(C, A, B) {
  if (C != null) {
    if ("number" == typeof C) {
      this.fromNumber(C, A, B)
    } else {
      if (A == null && "string" != typeof C) {
        this.fromString(C, 256)
      } else {
        this.fromString(C, A)
      }
    }
  }
}

function nbi() {
  return new BigInteger(null)
}

function am1(B, E, F, G, A, C) {
  while (--C >= 0) {
    var D = E * this[B++] + F[G] + A;
    A = Math.floor(D / 67108864);
    F[G++] = D & 67108863
  }
  return A
}

function am2(E, J, B, C, K, F) {
  var A = J & 32767,
    D = J >> 15;
  while (--F >= 0) {
    var H = this[E] & 32767;
    var G = this[E++] >> 15;
    var I = D * H + G * A;
    H = A * H + ((I & 32767) << 15) + B[C] + (K & 1073741823);
    K = (H >>> 30) + (I >>> 15) + D * G + (K >>> 30);
    B[C++] = H & 1073741823
  }
  return K
}

function am3(E, J, B, C, K, F) {
  var A = J & 16383,
    D = J >> 14;
  while (--F >= 0) {
    var H = this[E] & 16383;
    var G = this[E++] >> 14;
    var I = D * H + G * A;
    H = A * H + ((I & 16383) << 14) + B[C] + K;
    K = (H >> 28) + (I >> 14) + D * G;
    B[C++] = H & 268435455
  }
  return K
}
if (j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
  BigInteger.prototype.am = am2;
  dbits = 30
} else {
  if (j_lm && (navigator.appName != "Netscape")) {
    BigInteger.prototype.am = am1;
    dbits = 26
  } else {
    BigInteger.prototype.am = am3;
    dbits = 28
  }
}
BigInteger.prototype.DB = dbits;
BigInteger.prototype.DM = ((1 << dbits) - 1);
BigInteger.prototype.DV = (1 << dbits);
var BI_FP = 52;
BigInteger.prototype.FV = Math.pow(2, BI_FP);
BigInteger.prototype.F1 = BI_FP - dbits;
BigInteger.prototype.F2 = 2 * dbits - BI_FP;
var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
var BI_RC = [];
var rr, vv;
rr = "0".charCodeAt(0);
for (vv = 0; vv <= 9; vv += 1) {
  BI_RC[rr++] = vv
}
rr = "a".charCodeAt(0);
for (vv = 10; vv < 36; vv += 1) {
  BI_RC[rr++] = vv
}
rr = "A".charCodeAt(0);
for (vv = 10; vv < 36; vv += 1) {
  BI_RC[rr++] = vv
}

function int2char(A) {
  return BI_RM.charAt(A)
}

function intAt(B, A) {
  var C = BI_RC[B.charCodeAt(A)];
  return (C == null) ? -1 : C
}

function bnpCopyTo(A) {
  for (var B = this.t - 1; B >= 0; B -= 1) {
    A[B] = this[B]
  }
  A.t = this.t;
  A.s = this.s
}

function bnpFromInt(A) {
  this.t = 1;
  this.s = (A < 0) ? -1 : 0;
  if (A > 0) {
    this[0] = A
  } else {
    if (A < -1) {
      this[0] = A + this.DV
    } else {
      this.t = 0
    }
  }
}

function nbv(A) {
  var B = nbi();
  B.fromInt(A);
  return B
}

function bnpFromString(B, D) {
  var G;
  if (D == 16) {
    G = 4
  } else {
    if (D == 8) {
      G = 3
    } else {
      if (D == 256) {
        G = 8
      } else {
        if (D == 2) {
          G = 1
        } else {
          if (D == 32) {
            G = 5
          } else {
            if (D == 4) {
              G = 2
            } else {
              this.fromRadix(B, D);
              return
            }
          }
        }
      }
    }
  }
  this.t = 0;
  this.s = 0;
  var A = B.length,
    F = false,
    C = 0;
  while (--A >= 0) {
    var E = (G == 8) ? B[A] & 255 : intAt(B, A);
    if (E < 0) {
      if (B.charAt(A) == "-") {
        F = true
      }
      continue
    }
    F = false;
    if (C == 0) {
      this[this.t++] = E
    } else {
      if (C + G > this.DB) {
        this[this.t - 1] |= (E & ((1 << (this.DB - C)) - 1)) << C;
        this[this.t++] = (E >> (this.DB - C))
      } else {
        this[this.t - 1] |= E << C
      }
    }
    C += G;
    if (C >= this.DB) {
      C -= this.DB
    }
  }
  if (G == 8 && (B[0] & 128) != 0) {
    this.s = -1;
    if (C > 0) {
      this[this.t - 1] |= ((1 << (this.DB - C)) - 1) << C
    }
  }
  this.clamp();
  if (F) {
    BigInteger.ZERO.subTo(this, this)
  }
}

function bnpClamp() {
  var A = this.s & this.DM;
  while (this.t > 0 && this[this.t - 1] == A) {
    --this.t
  }
}

function bnToString(G) {
  if (this.s < 0) {
    return "-" + this.negate().toString(G)
  }
  var D;
  if (G == 16) {
    D = 4
  } else {
    if (G == 8) {
      D = 3
    } else {
      if (G == 2) {
        D = 1
      } else {
        if (G == 32) {
          D = 5
        } else {
          if (G == 4) {
            D = 2
          } else {
            return this.toRadix(G)
          }
        }
      }
    }
  }
  var C = (1 << D) - 1,
    H, F = false,
    A = "",
    E = this.t;
  var B = this.DB - (E * this.DB) % D;
  if (E-- > 0) {
    if (B < this.DB && (H = this[E] >> B) > 0) {
      F = true;
      A = int2char(H)
    }
    while (E >= 0) {
      if (B < D) {
        H = (this[E] & ((1 << B) - 1)) << (D - B);
        H |= this[E -= 1] >> (B += this.DB - D)
      } else {
        H = (this[E] >> (B -= D)) & C;
        if (B <= 0) {
          B += this.DB;
          E -= 1
        }
      }
      if (H > 0) {
        F = true
      }
      if (F) {
        A += int2char(H)
      }
    }
  }
  return F ? A : "0"
}

function bnNegate() {
  var A = nbi();
  BigInteger.ZERO.subTo(this, A);
  return A
}

function bnAbs() {
  return (this.s < 0) ? this.negate() : this
}

function bnCompareTo(C) {
  var A = this.s - C.s;
  if (A != 0) {
    return A
  }
  var B = this.t;
  A = B - C.t;
  if (A != 0) {
    return (this.s < 0) ? -A : A
  }
  while (--B >= 0) {
    if ((A = this[B] - C[B]) != 0) {
      return A
    }
  }
  return 0
}

function nbits(B) {
  var A = 1,
    C;
  if ((C = B >>> 16) != 0) {
    B = C;
    A += 16
  }
  if ((C = B >> 8) != 0) {
    B = C;
    A += 8
  }
  if ((C = B >> 4) != 0) {
    B = C;
    A += 4
  }
  if ((C = B >> 2) != 0) {
    B = C;
    A += 2
  }
  if ((C = B >> 1) != 0) {
    B = C;
    A += 1
  }
  return A
}

function bnBitLength() {
  if (this.t <= 0) {
    return 0
  }
  return this.DB * (this.t - 1) + nbits(this[this.t - 1] ^ (this.s & this.DM))
}

function bnpDLShiftTo(B, A) {
  var C;
  for (C = this.t - 1; C >= 0; C -= 1) {
    A[C + B] = this[C]
  }
  for (C = B - 1; C >= 0; C -= 1) {
    A[C] = 0
  }
  A.t = this.t + B;
  A.s = this.s
}

function bnpDRShiftTo(B, A) {
  for (var C = B; C < this.t; C += 1) {
    A[C - B] = this[C]
  }
  A.t = Math.max(this.t - B, 0);
  A.s = this.s
}

function bnpLShiftTo(G, A) {
  var B = G % this.DB;
  var E = this.DB - B;
  var C = (1 << E) - 1;
  var D = Math.floor(G / this.DB),
    H = (this.s << B) & this.DM,
    F;
  for (F = this.t - 1; F >= 0; F -= 1) {
    A[F + D + 1] = (this[F] >> E) | H;
    H = (this[F] & C) << B
  }
  for (F = D - 1; F >= 0; F -= 1) {
    A[F] = 0
  }
  A[D] = H;
  A.t = this.t + D + 1;
  A.s = this.s;
  A.clamp()
}

function bnpRShiftTo(C, B) {
  B.s = this.s;
  var A = Math.floor(C / this.DB);
  if (A >= this.t) {
    B.t = 0;
    return
  }
  var E = C % this.DB;
  var G = this.DB - E;
  var F = (1 << E) - 1;
  B[0] = this[A] >> E;
  for (var D = A + 1; D < this.t; D += 1) {
    B[D - A - 1] |= (this[D] & F) << G;
    B[D - A] = this[D] >> E
  }
  if (E > 0) {
    B[this.t - A - 1] |= (this.s & F) << G
  }
  B.t = this.t - A;
  B.clamp()
}

function bnpSubTo(E, A) {
  var B = 0,
    D = 0,
    C = Math.min(E.t, this.t);
  while (B < C) {
    D += this[B] - E[B];
    A[B++] = D & this.DM;
    D >>= this.DB
  }
  if (E.t < this.t) {
    D -= E.s;
    while (B < this.t) {
      D += this[B];
      A[B++] = D & this.DM;
      D >>= this.DB
    }
    D += this.s
  } else {
    D += this.s;
    while (B < E.t) {
      D -= E[B];
      A[B++] = D & this.DM;
      D >>= this.DB
    }
    D -= E.s
  }
  A.s = (D < 0) ? -1 : 0;
  if (D < -1) {
    A[B++] = this.DV + D
  } else {
    if (D > 0) {
      A[B++] = D
    }
  }
  A.t = B;
  A.clamp()
}

function bnpMultiplyTo(E, A) {
  var C = this.abs(),
    D = E.abs();
  var B = C.t;
  A.t = B + D.t;
  while (--B >= 0) {
    A[B] = 0
  }
  for (B = 0; B < D.t; B += 1) {
    A[B + C.t] = C.am(0, D[B], A, B, 0, C.t)
  }
  A.s = 0;
  A.clamp();
  if (this.s != E.s) {
    BigInteger.ZERO.subTo(A, A)
  }
}

function bnpSquareTo(A) {
  var C = this.abs();
  var B = A.t = 2 * C.t;
  while (--B >= 0) {
    A[B] = 0
  }
  for (B = 0; B < C.t - 1; B += 1) {
    var D = C.am(B, C[B], A, 2 * B, 0, 1);
    if ((A[B + C.t] += C.am(B + 1, 2 * C[B], A, 2 * B + 1, D, C.t - B - 1)) >= C.DV) {
      A[B + C.t] -= C.DV;
      A[B + C.t + 1] = 1
    }
  }
  if (A.t > 0) {
    A[A.t - 1] += C.am(B, C[B], A, 2 * B, 0, 1)
  }
  A.s = 0;
  A.clamp()
}

function bnpDivRemTo(I, B, A) {
  var K = I.abs();
  if (K.t <= 0) {
    return
  }
  var Q = this.abs();
  if (Q.t < K.t) {
    if (B != null) {
      B.fromInt(0)
    }
    if (A != null) {
      this.copyTo(A)
    }
    return
  }
  if (A == null) {
    A = nbi()
  }
  var S = nbi(),
    D = this.s,
    H = I.s;
  var C = this.DB - nbits(K[K.t - 1]);
  if (C > 0) {
    K.lShiftTo(C, S);
    Q.lShiftTo(C, A)
  } else {
    K.copyTo(S);
    Q.copyTo(A)
  }
  var R = S.t;
  var J = S[R - 1];
  if (J == 0) {
    return
  }
  var P = J * (1 << this.F1) + ((R > 1) ? S[R - 2] >> this.F2 : 0);
  var L = this.FV / P,
    N = (1 << this.F1) / P,
    M = 1 << this.F2;
  var G = A.t,
    F = G - R,
    E = (B == null) ? nbi() : B;
  S.dlShiftTo(F, E);
  if (A.compareTo(E) >= 0) {
    A[A.t++] = 1;
    A.subTo(E, A)
  }
  BigInteger.ONE.dlShiftTo(R, E);
  E.subTo(S, S);
  while (S.t < R) {
    S[S.t++] = 0
  }
  while (--F >= 0) {
    var O = (A[G -= 1] == J) ? this.DM : Math.floor(A[G] * L + (A[G - 1] + M) * N);
    if ((A[G] += S.am(0, O, A, F, 0, R)) < O) {
      S.dlShiftTo(F, E);
      A.subTo(E, A);
      while (A[G] < --O) {
        A.subTo(E, A)
      }
    }
  }
  if (B != null) {
    A.drShiftTo(R, B);
    if (D != H) {
      BigInteger.ZERO.subTo(B, B)
    }
  }
  A.t = R;
  A.clamp();
  if (C > 0) {
    A.rShiftTo(C, A)
  }
  if (D < 0) {
    BigInteger.ZERO.subTo(A, A)
  }
}

function bnMod(B) {
  var A = nbi();
  this.abs().divRemTo(B, null, A);
  if (this.s < 0 && A.compareTo(BigInteger.ZERO) > 0) {
    B.subTo(A, A)
  }
  return A
}

function Classic(A) {
  this.m = A
}

function cConvert(A) {
  if (A.s < 0 || A.compareTo(this.m) >= 0) {
    return A.mod(this.m)
  } else {
    return A
  }
}

function cRevert(A) {
  return A
}

function cReduce(A) {
  A.divRemTo(this.m, null, A)
}

function cMulTo(B, C, A) {
  B.multiplyTo(C, A);
  this.reduce(A)
}

function cSqrTo(B, A) {
  B.squareTo(A);
  this.reduce(A)
}
Classic.prototype.convert = cConvert;
Classic.prototype.revert = cRevert;
Classic.prototype.reduce = cReduce;
Classic.prototype.mulTo = cMulTo;
Classic.prototype.sqrTo = cSqrTo;

function bnpInvDigit() {
  if (this.t < 1) {
    return 0
  }
  var A = this[0];
  if ((A & 1) == 0) {
    return 0
  }
  var B = A & 3;
  B = (B * (2 - (A & 15) * B)) & 15;
  B = (B * (2 - (A & 255) * B)) & 255;
  B = (B * (2 - (((A & 65535) * B) & 65535))) & 65535;
  B = (B * (2 - A * B % this.DV)) % this.DV;
  return (B > 0) ? this.DV - B : -B
}

function Montgomery(A) {
  this.m = A;
  this.mp = A.invDigit();
  this.mpl = this.mp & 32767;
  this.mph = this.mp >> 15;
  this.um = (1 << (A.DB - 15)) - 1;
  this.mt2 = 2 * A.t
}

function montConvert(B) {
  var A = nbi();
  B.abs().dlShiftTo(this.m.t, A);
  A.divRemTo(this.m, null, A);
  if (B.s < 0 && A.compareTo(BigInteger.ZERO) > 0) {
    this.m.subTo(A, A)
  }
  return A
}

function montRevert(B) {
  var A = nbi();
  B.copyTo(A);
  this.reduce(A);
  return A
}

function montReduce(B) {
  while (B.t <= this.mt2) {
    B[B.t++] = 0
  }
  for (var A = 0; A < this.m.t; A += 1) {
    var D = B[A] & 32767;
    var C = (D * this.mpl + (((D * this.mph + (B[A] >> 15) * this.mpl) & this.um) << 15)) & B.DM;
    D = A + this.m.t;
    B[D] += this.m.am(0, C, B, A, 0, this.m.t);
    while (B[D] >= B.DV) {
      B[D] -= B.DV;
      B[D += 1] += 1
    }
  }
  B.clamp();
  B.drShiftTo(this.m.t, B);
  if (B.compareTo(this.m) >= 0) {
    B.subTo(this.m, B)
  }
}

function montSqrTo(B, A) {
  B.squareTo(A);
  this.reduce(A)
}

function montMulTo(B, C, A) {
  B.multiplyTo(C, A);
  this.reduce(A)
}
Montgomery.prototype.convert = montConvert;
Montgomery.prototype.revert = montRevert;
Montgomery.prototype.reduce = montReduce;
Montgomery.prototype.mulTo = montMulTo;
Montgomery.prototype.sqrTo = montSqrTo;

function bnpIsEven() {
  return ((this.t > 0) ? (this[0] & 1) : this.s) == 0
}

function bnpExp(C, E) {
  if (C > 4294967295 || C < 1) {
    return BigInteger.ONE
  }
  var B = nbi(),
    F = nbi(),
    A = E.convert(this),
    D = nbits(C) - 1;
  A.copyTo(B);
  while (--D >= 0) {
    E.sqrTo(B, F);
    if ((C & (1 << D)) > 0) {
      E.mulTo(F, A, B)
    } else {
      var G = B;
      B = F;
      F = G
    }
  }
  return E.revert(B)
}

function bnModPowInt(A, C) {
  var B;
  if (A < 256 || C.isEven()) {
    B = new Classic(C)
  } else {
    B = new Montgomery(C)
  }
  return this.exp(A, B)
}
BigInteger.prototype.copyTo = bnpCopyTo;
BigInteger.prototype.fromInt = bnpFromInt;
BigInteger.prototype.fromString = bnpFromString;
BigInteger.prototype.clamp = bnpClamp;
BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
BigInteger.prototype.drShiftTo = bnpDRShiftTo;
BigInteger.prototype.lShiftTo = bnpLShiftTo;
BigInteger.prototype.rShiftTo = bnpRShiftTo;
BigInteger.prototype.subTo = bnpSubTo;
BigInteger.prototype.multiplyTo = bnpMultiplyTo;
BigInteger.prototype.squareTo = bnpSquareTo;
BigInteger.prototype.divRemTo = bnpDivRemTo;
BigInteger.prototype.invDigit = bnpInvDigit;
BigInteger.prototype.isEven = bnpIsEven;
BigInteger.prototype.exp = bnpExp;
BigInteger.prototype.toString = bnToString;
BigInteger.prototype.negate = bnNegate;
BigInteger.prototype.abs = bnAbs;
BigInteger.prototype.compareTo = bnCompareTo;
BigInteger.prototype.bitLength = bnBitLength;
BigInteger.prototype.mod = bnMod;
BigInteger.prototype.modPowInt = bnModPowInt;
BigInteger.ZERO = nbv(0);
BigInteger.ONE = nbv(1);

function bnClone() {
  var A = nbi();
  this.copyTo(A);
  return A
}

function bnIntValue() {
  if (this.s < 0) {
    if (this.t == 1) {
      return this[0] - this.DV
    } else {
      if (this.t == 0) {
        return -1
      }
    }
  } else {
    if (this.t == 1) {
      return this[0]
    } else {
      if (this.t == 0) {
        return 0
      }
    }
  }
  return ((this[1] & ((1 << (32 - this.DB)) - 1)) << this.DB) | this[0]
}

function bnByteValue() {
  return (this.t == 0) ? this.s : (this[0] << 24) >> 24
}

function bnShortValue() {
  return (this.t == 0) ? this.s : (this[0] << 16) >> 16
}

function bnpChunkSize(A) {
  return Math.floor(Math.LN2 * this.DB / Math.log(A))
}

function bnSigNum() {
  if (this.s < 0) {
    return -1
  } else {
    if (this.t <= 0 || (this.t == 1 && this[0] <= 0)) {
      return 0
    } else {
      return 1
    }
  }
}

function bnpToRadix(D) {
  if (D == null) {
    D = 10
  }
  if (this.signum() == 0 || D < 2 || D > 36) {
    return "0"
  }
  var F = this.chunkSize(D);
  var G = Math.pow(D, F);
  var A = nbv(G),
    E = nbi(),
    C = nbi(),
    B = "";
  this.divRemTo(A, E, C);
  while (E.signum() > 0) {
    B = (G + C.intValue()).toString(D).substr(1) + B;
    E.divRemTo(A, E, C)
  }
  return C.intValue().toString(D) + B
}

function bnpFromRadix(A, G) {
  this.fromInt(0);
  if (G == null) {
    G = 10
  }
  var B = this.chunkSize(G);
  var I = Math.pow(G, B),
    E = false,
    D = 0,
    C = 0;
  for (var F = 0; F < A.length; F += 1) {
    var H = intAt(A, F);
    if (H < 0) {
      if (A.charAt(F) == "-" && this.signum() == 0) {
        E = true
      }
      continue
    }
    C = G * C + H;
    if (++D >= B) {
      this.dMultiply(I);
      this.dAddOffset(C, 0);
      D = 0;
      C = 0
    }
  }
  if (D > 0) {
    this.dMultiply(Math.pow(G, D));
    this.dAddOffset(C, 0)
  }
  if (E) {
    BigInteger.ZERO.subTo(this, this)
  }
}

function bnpFromNumber(G, E, H) {
  if ("number" == typeof E) {
    if (G < 2) {
      this.fromInt(1)
    } else {
      this.fromNumber(G, H);
      if (!this.testBit(G - 1)) {
        this.bitwiseTo(BigInteger.ONE.shiftLeft(G - 1), op_or, this)
      }
      if (this.isEven()) {
        this.dAddOffset(1, 0)
      }
      while (!this.isProbablePrime(E)) {
        this.dAddOffset(2, 0);
        if (this.bitLength() > G) {
          this.subTo(BigInteger.ONE.shiftLeft(G - 1), this)
        }
      }
    }
  } else {
    var F = [],
      B = G & 7;
    F.length = (G >> 3) + 1;
    E.nextBytes(F);
    if (B > 0) {
      F[0] &= ((1 << B) - 1)
    } else {
      F[0] = 0
    }
    if (myBrowser() == "FF" && window.crypto) {
      var C = new ArrayBuffer(32);
      var A = new Int8Array(C);
      window.crypto.getRandomValues(A);
      for (H = 0; H < A.length; ++H) {
        F[H] = A[H] & 255
      }
    } else {
      if (myBrowser() == "IE11") {
        var C = new ArrayBuffer(32);
        var A = new Int8Array(C);
        var D = window.crypto || window.msCrypto;
        D.getRandomValues(A);
        for (H = 0; H < A.length; ++H) {
          F[H] = A[H] & 255
        }
      } else {
        if (myBrowser() == "edge") {
          var C = new ArrayBuffer(32);
          var A = new Int8Array(C);
          var D = window.crypto || window.msCrypto;
          D.getRandomValues(A);
          for (H = 0; H < A.length; ++H) {
            F[H] = A[H] & 255
          }
        }
      }
    }
    this.fromString(F, 256)
  }
}

function bnToByteArray() {
  var A = this.t,
    B = [];
  B[0] = this.s;
  var C = this.DB - (A * this.DB) % 8,
    D, E = 0;
  if (A-- > 0) {
    if (C < this.DB && (D = this[A] >> C) != (this.s & this.DM) >> C) {
      B[E++] = D | (this.s << (this.DB - C))
    }
    while (A >= 0) {
      if (C < 8) {
        D = (this[A] & ((1 << C) - 1)) << (8 - C);
        D |= this[A -= 1] >> (C += this.DB - 8)
      } else {
        D = (this[A] >> (C -= 8)) & 255;
        if (C <= 0) {
          C += this.DB;
          A -= 1
        }
      }
      if ((D & 128) != 0) {
        D |= -256
      }
      if (E == 0 && (this.s & 128) != (D & 128)) {
        ++E
      }
      if (E > 0 || D != this.s) {
        B[E++] = D
      }
    }
  }
  return B
}

function bnEquals(A) {
  return (this.compareTo(A) == 0)
}

function bnMin(A) {
  return (this.compareTo(A) < 0) ? this : A
}

function bnMax(A) {
  return (this.compareTo(A) > 0) ? this : A
}

function bnpBitwiseTo(E, C, A) {
  var B, F, D = Math.min(E.t, this.t);
  for (B = 0; B < D; B += 1) {
    A[B] = C(this[B], E[B])
  }
  if (E.t < this.t) {
    F = E.s & this.DM;
    for (B = D; B < this.t; B += 1) {
      A[B] = C(this[B], F)
    }
    A.t = this.t
  } else {
    F = this.s & this.DM;
    for (B = D; B < E.t; B += 1) {
      A[B] = C(F, E[B])
    }
    A.t = E.t
  }
  A.s = C(this.s, E.s);
  A.clamp()
}

function op_and(A, B) {
  return A & B
}

function bnAnd(B) {
  var A = nbi();
  this.bitwiseTo(B, op_and, A);
  return A
}

function op_or(A, B) {
  return A | B
}

function bnOr(B) {
  var A = nbi();
  this.bitwiseTo(B, op_or, A);
  return A
}

function op_xor(A, B) {
  return A ^ B
}

function bnXor(B) {
  var A = nbi();
  this.bitwiseTo(B, op_xor, A);
  return A
}

function op_andnot(A, B) {
  return A & ~B
}

function bnAndNot(B) {
  var A = nbi();
  this.bitwiseTo(B, op_andnot, A);
  return A
}

function bnNot() {
  var A = nbi();
  for (var B = 0; B < this.t; B += 1) {
    A[B] = this.DM & ~this[B]
  }
  A.t = this.t;
  A.s = ~this.s;
  return A
}

function bnShiftLeft(B) {
  var A = nbi();
  if (B < 0) {
    this.rShiftTo(-B, A)
  } else {
    this.lShiftTo(B, A)
  }
  return A
}

function bnShiftRight(B) {
  var A = nbi();
  if (B < 0) {
    this.lShiftTo(-B, A)
  } else {
    this.rShiftTo(B, A)
  }
  return A
}

function lbit(B) {
  if (B == 0) {
    return -1
  }
  var A = 0;
  if ((B & 65535) == 0) {
    B >>= 16;
    A += 16
  }
  if ((B & 255) == 0) {
    B >>= 8;
    A += 8
  }
  if ((B & 15) == 0) {
    B >>= 4;
    A += 4
  }
  if ((B & 3) == 0) {
    B >>= 2;
    A += 2
  }
  if ((B & 1) == 0) {
    ++A
  }
  return A
}

function bnGetLowestSetBit() {
  for (var A = 0; A < this.t; A += 1) {
    if (this[A] != 0) {
      return A * this.DB + lbit(this[A])
    }
  }
  if (this.s < 0) {
    return this.t * this.DB
  }
  return -1
}

function cbit(B) {
  var A = 0;
  while (B != 0) {
    B &= B - 1;
    A += 1
  }
  return A
}

function bnBitCount() {
  var A = 0,
    C = this.s & this.DM;
  for (var B = 0; B < this.t; B += 1) {
    A += cbit(this[B] ^ C)
  }
  return A
}

function bnTestBit(A) {
  var B = Math.floor(A / this.DB);
  if (B >= this.t) {
    return (this.s != 0)
  }
  return ((this[B] & (1 << (A % this.DB))) != 0)
}

function bnpChangeBit(B, C) {
  var A = BigInteger.ONE.shiftLeft(B);
  this.bitwiseTo(A, C, A);
  return A
}

function bnSetBit(A) {
  return this.changeBit(A, op_or)
}

function bnClearBit(A) {
  return this.changeBit(A, op_andnot)
}

function bnFlipBit(A) {
  return this.changeBit(A, op_xor)
}

function bnpAddTo(E, A) {
  var B = 0,
    D = 0,
    C = Math.min(E.t, this.t);
  while (B < C) {
    D += this[B] + E[B];
    A[B++] = D & this.DM;
    D >>= this.DB
  }
  if (E.t < this.t) {
    D += E.s;
    while (B < this.t) {
      D += this[B];
      A[B++] = D & this.DM;
      D >>= this.DB
    }
    D += this.s
  } else {
    D += this.s;
    while (B < E.t) {
      D += E[B];
      A[B++] = D & this.DM;
      D >>= this.DB
    }
    D += E.s
  }
  A.s = (D < 0) ? -1 : 0;
  if (D > 0) {
    A[B++] = D
  } else {
    if (D < -1) {
      A[B++] = this.DV + D
    }
  }
  A.t = B;
  A.clamp()
}

function bnAdd(B) {
  var A = nbi();
  this.addTo(B, A);
  return A
}

function bnSubtract(B) {
  var A = nbi();
  this.subTo(B, A);
  return A
}

function bnMultiply(B) {
  var A = nbi();
  this.multiplyTo(B, A);
  return A
}

function bnSquare() {
  var A = nbi();
  this.squareTo(A);
  return A
}

function bnDivide(B) {
  var A = nbi();
  this.divRemTo(B, A, null);
  return A
}

function bnRemainder(B) {
  var A = nbi();
  this.divRemTo(B, null, A);
  return A
}

function bnDivideAndRemainder(C) {
  var B = nbi(),
    A = nbi();
  this.divRemTo(C, B, A);
  return [B, A]
}

function bnpDMultiply(A) {
  this[this.t] = this.am(0, A - 1, this, 0, 0, this.t);
  ++this.t;
  this.clamp()
}

function bnpDAddOffset(A, B) {
  if (A == 0) {
    return
  }
  while (this.t <= B) {
    this[this.t++] = 0
  }
  this[B] += A;
  while (this[B] >= this.DV) {
    this[B] -= this.DV;
    if (++B >= this.t) {
      this[this.t++] = 0
    }++this[B]
  }
}

function NullExp() {}

function nNop(A) {
  return A
}

function nMulTo(B, C, A) {
  B.multiplyTo(C, A)
}

function nSqrTo(B, A) {
  B.squareTo(A)
}
NullExp.prototype.convert = nNop;
NullExp.prototype.revert = nNop;
NullExp.prototype.mulTo = nMulTo;
NullExp.prototype.sqrTo = nSqrTo;

function bnPow(A) {
  return this.exp(A, new NullExp())
}

function bnpMultiplyLowerTo(D, B, A) {
  var C = Math.min(this.t + D.t, B);
  A.s = 0;
  A.t = C;
  while (C > 0) {
    A[C -= 1] = 0
  }
  var E;
  for (E = A.t - this.t; C < E; C += 1) {
    A[C + this.t] = this.am(0, D[C], A, C, 0, this.t)
  }
  for (E = Math.min(D.t, B); C < E; C += 1) {
    this.am(0, D[C], A, C, 0, B - C)
  }
  A.clamp()
}

function bnpMultiplyUpperTo(D, B, A) {
  B -= 1;
  var C = A.t = this.t + D.t - B;
  A.s = 0;
  while (--C >= 0) {
    A[C] = 0
  }
  for (C = Math.max(B - this.t, 0); C < D.t; C += 1) {
    A[this.t + C - B] = this.am(B - C, D[C], A, 0, 0, this.t + C - B)
  }
  A.clamp();
  A.drShiftTo(1, A)
}

function Barrett(A) {
  this.r2 = nbi();
  this.q3 = nbi();
  BigInteger.ONE.dlShiftTo(2 * A.t, this.r2);
  this.mu = this.r2.divide(A);
  this.m = A
}

function barrettConvert(B) {
  if (B.s < 0 || B.t > 2 * this.m.t) {
    return B.mod(this.m)
  } else {
    if (B.compareTo(this.m) < 0) {
      return B
    } else {
      var A = nbi();
      B.copyTo(A);
      this.reduce(A);
      return A
    }
  }
}

function barrettRevert(A) {
  return A
}

function barrettReduce(A) {
  A.drShiftTo(this.m.t - 1, this.r2);
  if (A.t > this.m.t + 1) {
    A.t = this.m.t + 1;
    A.clamp()
  }
  this.mu.multiplyUpperTo(this.r2, this.m.t + 1, this.q3);
  this.m.multiplyLowerTo(this.q3, this.m.t + 1, this.r2);
  while (A.compareTo(this.r2) < 0) {
    A.dAddOffset(1, this.m.t + 1)
  }
  A.subTo(this.r2, A);
  while (A.compareTo(this.m) >= 0) {
    A.subTo(this.m, A)
  }
}

function barrettSqrTo(B, A) {
  B.squareTo(A);
  this.reduce(A)
}

function barrettMulTo(B, C, A) {
  B.multiplyTo(C, A);
  this.reduce(A)
}
Barrett.prototype.convert = barrettConvert;
Barrett.prototype.revert = barrettRevert;
Barrett.prototype.reduce = barrettReduce;
Barrett.prototype.mulTo = barrettMulTo;
Barrett.prototype.sqrTo = barrettSqrTo;

function bnModPow(C, K) {
  var H = C.bitLength(),
    G, A = nbv(1),
    M;
  if (H <= 0) {
    return A
  } else {
    if (H < 18) {
      G = 1
    } else {
      if (H < 48) {
        G = 3
      } else {
        if (H < 144) {
          G = 4
        } else {
          if (H < 768) {
            G = 5
          } else {
            G = 6
          }
        }
      }
    }
  }
  if (H < 8) {
    M = new Classic(K)
  } else {
    if (K.isEven()) {
      M = new Barrett(K)
    } else {
      M = new Montgomery(K)
    }
  }
  var O = [],
    I = 3,
    N = G - 1,
    P = (1 << G) - 1;
  O[1] = M.convert(this);
  if (G > 1) {
    var L = nbi();
    M.sqrTo(O[1], L);
    while (I <= P) {
      O[I] = nbi();
      M.mulTo(L, O[I - 2], O[I]);
      I += 2
    }
  }
  var F = C.t - 1,
    D, B = true,
    J = nbi(),
    E;
  H = nbits(C[F]) - 1;
  while (F >= 0) {
    if (H >= N) {
      D = (C[F] >> (H - N)) & P
    } else {
      D = (C[F] & ((1 << (H + 1)) - 1)) << (N - H);
      if (F > 0) {
        D |= C[F - 1] >> (this.DB + H - N)
      }
    }
    I = G;
    while ((D & 1) == 0) {
      D >>= 1;
      I -= 1
    }
    if ((H -= I) < 0) {
      H += this.DB;
      F -= 1
    }
    if (B) {
      O[D].copyTo(A);
      B = false
    } else {
      while (I > 1) {
        M.sqrTo(A, J);
        M.sqrTo(J, A);
        I -= 2
      }
      if (I > 0) {
        M.sqrTo(A, J)
      } else {
        E = A;
        A = J;
        J = E
      }
      M.mulTo(J, O[D], A)
    }
    while (F >= 0 && (C[F] & (1 << H)) == 0) {
      M.sqrTo(A, J);
      E = A;
      A = J;
      J = E;
      if (--H < 0) {
        H = this.DB - 1;
        F -= 1
      }
    }
  }
  return M.revert(A)
}

function bnGCD(F) {
  var C = (this.s < 0) ? this.negate() : this.clone();
  var D = (F.s < 0) ? F.negate() : F.clone();
  if (C.compareTo(D) < 0) {
    var E = C;
    C = D;
    D = E
  }
  var B = C.getLowestSetBit(),
    A = D.getLowestSetBit();
  if (A < 0) {
    return C
  }
  if (B < A) {
    A = B
  }
  if (A > 0) {
    C.rShiftTo(A, C);
    D.rShiftTo(A, D)
  }
  while (C.signum() > 0) {
    if ((B = C.getLowestSetBit()) > 0) {
      C.rShiftTo(B, C)
    }
    if ((B = D.getLowestSetBit()) > 0) {
      D.rShiftTo(B, D)
    }
    if (C.compareTo(D) >= 0) {
      C.subTo(D, C);
      C.rShiftTo(1, C)
    } else {
      D.subTo(C, D);
      D.rShiftTo(1, D)
    }
  }
  if (A > 0) {
    D.lShiftTo(A, D)
  }
  return D
}

function bnpModInt(B) {
  if (B <= 0) {
    return 0
  }
  var A = this.DV % B,
    C = (this.s < 0) ? B - 1 : 0;
  if (this.t > 0) {
    if (A == 0) {
      C = this[0] % B
    } else {
      for (var D = this.t - 1; D >= 0; D -= 1) {
        C = (A * C + this[D]) % B
      }
    }
  }
  return C
}

function bnModInverse(D) {
  var A = D.isEven();
  if ((this.isEven() && A) || D.signum() == 0) {
    return BigInteger.ZERO
  }
  var C = D.clone(),
    B = this.clone();
  var G = nbv(1),
    E = nbv(0),
    F = nbv(0),
    H = nbv(1);
  while (C.signum() != 0) {
    while (C.isEven()) {
      C.rShiftTo(1, C);
      if (A) {
        if (!G.isEven() || !E.isEven()) {
          G.addTo(this, G);
          E.subTo(D, E)
        }
        G.rShiftTo(1, G)
      } else {
        if (!E.isEven()) {
          E.subTo(D, E)
        }
      }
      E.rShiftTo(1, E)
    }
    while (B.isEven()) {
      B.rShiftTo(1, B);
      if (A) {
        if (!F.isEven() || !H.isEven()) {
          F.addTo(this, F);
          H.subTo(D, H)
        }
        F.rShiftTo(1, F)
      } else {
        if (!H.isEven()) {
          H.subTo(D, H)
        }
      }
      H.rShiftTo(1, H)
    }
    if (C.compareTo(B) >= 0) {
      C.subTo(B, C);
      if (A) {
        G.subTo(F, G)
      }
      E.subTo(H, E)
    } else {
      B.subTo(C, B);
      if (A) {
        F.subTo(G, F)
      }
      H.subTo(E, H)
    }
  }
  if (B.compareTo(BigInteger.ONE) != 0) {
    return BigInteger.ZERO
  }
  if (H.compareTo(D) >= 0) {
    return H.subtract(D)
  }
  if (H.signum() < 0) {
    H.addTo(D, H)
  } else {
    return H
  }
  if (H.signum() < 0) {
    return H.add(D)
  } else {
    return H
  }
}
var lowprimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997];
var lplim = (1 << 26) / lowprimes[lowprimes.length - 1];

function bnIsProbablePrime(D) {
  var A, C = this.abs();
  if (C.t == 1 && C[0] <= lowprimes[lowprimes.length - 1]) {
    for (A = 0; A < lowprimes.length; A += 1) {
      if (C[0] == lowprimes[A]) {
        return true
      }
    }
    return false
  }
  if (C.isEven()) {
    return false
  }
  A = 1;
  while (A < lowprimes.length) {
    var B = lowprimes[A],
      E = A + 1;
    while (E < lowprimes.length && B < lplim) {
      B *= lowprimes[E++]
    }
    B = C.modInt(B);
    while (A < E) {
      if (B % lowprimes[A++] == 0) {
        return false
      }
    }
  }
  return C.millerRabin(D)
}

function bnpMillerRabin(B) {
  var H = this.subtract(BigInteger.ONE);
  var D = H.getLowestSetBit();
  if (D <= 0) {
    return false
  }
  var A = H.shiftRight(D);
  B = (B + 1) >> 1;
  if (B > lowprimes.length) {
    B = lowprimes.length
  }
  var G = nbi();
  for (var E = 0; E < B; E += 1) {
    G.fromInt(lowprimes[Math.floor(window.crypto.getRandomValues(new Uint8Array(1))*0.001 * lowprimes.length)]);
    var F = G.modPow(A, this);
    if (F.compareTo(BigInteger.ONE) != 0 && F.compareTo(H) != 0) {
      var C = 1;
      while (C++ < D && F.compareTo(H) != 0) {
        F = F.modPowInt(2, this);
        if (F.compareTo(BigInteger.ONE) == 0) {
          return false
        }
      }
      if (F.compareTo(H) != 0) {
        return false
      }
    }
  }
  return true
}
BigInteger.prototype.chunkSize = bnpChunkSize;
BigInteger.prototype.toRadix = bnpToRadix;
BigInteger.prototype.fromRadix = bnpFromRadix;
BigInteger.prototype.fromNumber = bnpFromNumber;
BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
BigInteger.prototype.changeBit = bnpChangeBit;
BigInteger.prototype.addTo = bnpAddTo;
BigInteger.prototype.dMultiply = bnpDMultiply;
BigInteger.prototype.dAddOffset = bnpDAddOffset;
BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
BigInteger.prototype.modInt = bnpModInt;
BigInteger.prototype.millerRabin = bnpMillerRabin;
BigInteger.prototype.clone = bnClone;
BigInteger.prototype.intValue = bnIntValue;
BigInteger.prototype.byteValue = bnByteValue;
BigInteger.prototype.shortValue = bnShortValue;
BigInteger.prototype.signum = bnSigNum;
BigInteger.prototype.toByteArray = bnToByteArray;
BigInteger.prototype.equals = bnEquals;
BigInteger.prototype.min = bnMin;
BigInteger.prototype.max = bnMax;
BigInteger.prototype.and = bnAnd;
BigInteger.prototype.or = bnOr;
BigInteger.prototype.xor = bnXor;
BigInteger.prototype.andNot = bnAndNot;
BigInteger.prototype.not = bnNot;
BigInteger.prototype.shiftLeft = bnShiftLeft;
BigInteger.prototype.shiftRight = bnShiftRight;
BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
BigInteger.prototype.bitCount = bnBitCount;
BigInteger.prototype.testBit = bnTestBit;
BigInteger.prototype.setBit = bnSetBit;
BigInteger.prototype.clearBit = bnClearBit;
BigInteger.prototype.flipBit = bnFlipBit;
BigInteger.prototype.add = bnAdd;
BigInteger.prototype.subtract = bnSubtract;
BigInteger.prototype.multiply = bnMultiply;
BigInteger.prototype.divide = bnDivide;
BigInteger.prototype.remainder = bnRemainder;
BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
BigInteger.prototype.modPow = bnModPow;
BigInteger.prototype.modInverse = bnModInverse;
BigInteger.prototype.pow = bnPow;
BigInteger.prototype.gcd = bnGCD;
BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
BigInteger.prototype.square = bnSquare;

// function Arcfour() {
//   this.i = 0;
//   this.j = 0;
//   this.S = []
// }

// function ARC4init(A) {
//   var B, D, C;
//   for (B = 0; B < 256; B += 1) {
//     this.S[B] = B
//   }
//   D = 0;
//   for (B = 0; B < 256; B += 1) {
//     D = (D + this.S[B] + A[B % A.length]) & 255;
//     C = this.S[B];
//     this.S[B] = this.S[D];
//     this.S[D] = C
//   }
//   this.i = 0;
//   this.j = 0
// }

// function ARC4next() {
//   var A;
//   this.i = (this.i + 1) & 255;
//   this.j = (this.j + this.S[this.i]) & 255;
//   A = this.S[this.i];
//   this.S[this.i] = this.S[this.j];
//   this.S[this.j] = A;
//   return this.S[(A + this.S[this.i]) & 255]
// }
// Arcfour.prototype.init = ARC4init;
// Arcfour.prototype.next = ARC4next;

// function prng_newstate() {
//   return new Arcfour()
// }
var rng_psize = 256;
var rng_state;
var rng_pool;
var rng_pptr;

function rng_seed_int(A) {
  rng_pool[rng_pptr++] ^= A & 255;
  rng_pool[rng_pptr++] ^= (A >> 8) & 255;
  rng_pool[rng_pptr++] ^= (A >> 16) & 255;
  rng_pool[rng_pptr++] ^= (A >> 24) & 255;
  if (rng_pptr >= rng_psize) {
    rng_pptr -= rng_psize
  }
}

function rng_seed_time() {
  rng_seed_int(new Date().getTime())
}
if (rng_pool == null) {
  rng_pool = [];
  rng_pptr = 0;
  var t;
  if (window.crypto && window.crypto.getRandomValues) {
    var ua = new Uint8Array(32);
    window.crypto.getRandomValues(ua);
    for (t = 0; t < 32; t += 1) {
      rng_pool[rng_pptr++] = ua[t]
    }
  }
  if (navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) {
    var z = window.crypto.random(32);
    for (t = 0; t < z.length; t += 1) {
      rng_pool[rng_pptr++] = z.charCodeAt(t) & 255
    }
  }
  while (rng_pptr < rng_psize) {
    t = Math.floor(window.crypto.getRandomValues(new Uint16Array(1))[0]);
    rng_pool[rng_pptr++] = t >>> 8;
    rng_pool[rng_pptr++] = t & 255
  }
  rng_pptr = 0;
  rng_seed_time()
}

function rng_get_byte() {
  if (rng_state == null) {
    rng_seed_time();
    rng_state = prng_newstate();
    rng_state.init(rng_pool);
    for (rng_pptr = 0; rng_pptr < rng_pool.length; rng_pptr += 1) {
      rng_pool[rng_pptr] = 0
    }
    rng_pptr = 0
  }
  return rng_state.next()
}

function rng_get_bytes(B) {
  var A;
  for (A = 0; A < B.length; A += 1) {
    B[A] = rng_get_byte()
  }
}

function SecureRandom() {}
SecureRandom.prototype.nextBytes = rng_get_bytes;

function ECFieldElementFp(A, B) {
  this.x = B;
  this.q = A
}

function feFpEquals(A) {
  if (A == this) {
    return true
  }
  return (this.q.equals(A.q) && this.x.equals(A.x))
}

function feFpToBigInteger() {
  return this.x
}

function feFpNegate() {
  return new ECFieldElementFp(this.q, this.x.negate().mod(this.q))
}

function feFpAdd(A) {
  return new ECFieldElementFp(this.q, this.x.add(A.toBigInteger()).mod(this.q))
}

function feFpSubtract(A) {
  return new ECFieldElementFp(this.q, this.x.subtract(A.toBigInteger()).mod(this.q))
}

function feFpMultiply(A) {
  return new ECFieldElementFp(this.q, this.x.multiply(A.toBigInteger()).mod(this.q))
}

function feFpSquare() {
  return new ECFieldElementFp(this.q, this.x.square().mod(this.q))
}

function feFpDivide(A) {
  return new ECFieldElementFp(this.q, this.x.multiply(A.toBigInteger().modInverse(this.q)).mod(this.q))
}
ECFieldElementFp.prototype.equals = feFpEquals;
ECFieldElementFp.prototype.toBigInteger = feFpToBigInteger;
ECFieldElementFp.prototype.negate = feFpNegate;
ECFieldElementFp.prototype.add = feFpAdd;
ECFieldElementFp.prototype.subtract = feFpSubtract;
ECFieldElementFp.prototype.multiply = feFpMultiply;
ECFieldElementFp.prototype.square = feFpSquare;
ECFieldElementFp.prototype.divide = feFpDivide;

function ECPointFp(D, B, C, A) {
  this.curve = D;
  this.x = B;
  this.y = C;
  if (A == null) {
    this.z = BigInteger.ONE
  } else {
    this.z = A
  }
  this.zinv = null
}

function pointFpGetX() {
  if (this.zinv == null) {
    this.zinv = this.z.modInverse(this.curve.q)
  }
  return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q))
}

function pointFpGetY() {
  if (this.zinv == null) {
    this.zinv = this.z.modInverse(this.curve.q)
  }
  return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q))
}

function pointFpEquals(C) {
  if (C == this) {
    return true
  }
  if (this.isInfinity()) {
    return C.isInfinity()
  }
  if (C.isInfinity()) {
    return this.isInfinity()
  }
  var B, A;
  B = C.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(C.z)).mod(this.curve.q);
  if (!B.equals(BigInteger.ZERO)) {
    return false
  }
  A = C.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(C.z)).mod(this.curve.q);
  return A.equals(BigInteger.ZERO)
}

function pointFpIsInfinity() {
  if ((this.x == null) && (this.y == null)) {
    return true
  }
  return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO)
}

function pointFpNegate() {
  return new ECPointFp(this.curve, this.x, this.y.negate(), this.z)
}

function pointFpAdd(L) {
  if (this.isInfinity()) {
    return L
  }
  if (L.isInfinity()) {
    return this
  }
  var E = L.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(L.z)).mod(this.curve.q);
  var C = L.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(L.z)).mod(this.curve.q);
  if (BigInteger.ZERO.equals(C)) {
    if (BigInteger.ZERO.equals(E)) {
      return this.twice()
    }
    return this.curve.getInfinity()
  }
  var F = new BigInteger("3");
  var K = this.x.toBigInteger();
  var D = this.y.toBigInteger();
  var H = L.x.toBigInteger();
  var I = L.y.toBigInteger();
  var M = C.square();
  var J = M.multiply(C);
  var N = K.multiply(M);
  var B = E.square().multiply(this.z);
  var A = B.subtract(N.shiftLeft(1)).multiply(L.z).subtract(J).multiply(C).mod(this.curve.q);
  var O = N.multiply(F).multiply(E).subtract(D.multiply(J)).subtract(B.multiply(E)).multiply(L.z).add(E.multiply(J)).mod(this.curve.q);
  var G = J.multiply(this.z).multiply(L.z).mod(this.curve.q);
  return new ECPointFp(this.curve, this.curve.fromBigInteger(A), this.curve.fromBigInteger(O), G)
}

function pointFpTwice() {
  if (this.isInfinity()) {
    return this
  }
  if (this.y.toBigInteger().signum() == 0) {
    return this.curve.getInfinity()
  }
  var E = new BigInteger("3");
  var B = this.x.toBigInteger();
  var C = this.y.toBigInteger();
  var F = C.multiply(this.z);
  var I = F.multiply(C).mod(this.curve.q);
  var J = this.curve.a.toBigInteger();
  var D = B.square().multiply(E);
  if (!BigInteger.ZERO.equals(J)) {
    D = D.add(this.z.square().multiply(J))
  }
  D = D.mod(this.curve.q);
  var G = D.square().subtract(B.shiftLeft(3).multiply(I)).shiftLeft(1).multiply(F).mod(this.curve.q);
  var H = D.multiply(E).multiply(B).subtract(I.shiftLeft(1)).shiftLeft(2).multiply(I).subtract(D.square().multiply(D)).mod(this.curve.q);
  var A = F.square().multiply(F).shiftLeft(3).mod(this.curve.q);
  return new ECPointFp(this.curve, this.curve.fromBigInteger(G), this.curve.fromBigInteger(H), A)
}

function pointFpMultiply(D) {
  if (this.isInfinity()) {
    return this
  }
  if (D.signum() == 0) {
    return this.curve.getInfinity()
  }
  var A = D;
  var E = A.multiply(new BigInteger("3"));
  var B = this.negate();
  var G = this;
  var F;
  for (F = E.bitLength() - 2; F > 0; F -= 1) {
    G = G.twice();
    var H = E.testBit(F);
    var C = A.testBit(F);
    if (H != C) {
      G = G.add(H ? this : B)
    }
  }
  return G
}

function pointFpMultiplyTwo(E, C, F) {
  var A;
  if (E.bitLength() > F.bitLength()) {
    A = E.bitLength() - 1
  } else {
    A = F.bitLength() - 1
  }
  var B = this.curve.getInfinity();
  var D = this.add(C);
  while (A >= 0) {
    B = B.twice();
    if (E.testBit(A)) {
      if (F.testBit(A)) {
        B = B.add(D)
      } else {
        B = B.add(this)
      }
    } else {
      if (F.testBit(A)) {
        B = B.add(C)
      }
    }
    A -= 1
  }
  return B
}
ECPointFp.prototype.getX = pointFpGetX;
ECPointFp.prototype.getY = pointFpGetY;
ECPointFp.prototype.equals = pointFpEquals;
ECPointFp.prototype.isInfinity = pointFpIsInfinity;
ECPointFp.prototype.negate = pointFpNegate;
ECPointFp.prototype.add = pointFpAdd;
ECPointFp.prototype.twice = pointFpTwice;
ECPointFp.prototype.multiply = pointFpMultiply;
ECPointFp.prototype.multiplyTwo = pointFpMultiplyTwo;

function ECCurveFp(A, C, B) {
  this.q = A;
  this.a = this.fromBigInteger(C);
  this.b = this.fromBigInteger(B);
  this.infinity = new ECPointFp(this, null, null)
}

function curveFpGetQ() {
  return this.q
}

function curveFpGetA() {
  return this.a
}

function curveFpGetB() {
  return this.b
}

function curveFpEquals(A) {
  if (A == this) {
    return true
  }
  return (this.q.equals(A.q) && this.a.equals(A.a) && this.b.equals(A.b))
}

function curveFpGetInfinity() {
  return this.infinity
}

function curveFpFromBigInteger(A) {
  return new ECFieldElementFp(this.q, A)
}

function curveFpDecodePointHex(B) {
  switch (parseInt(B.substr(0, 2), 16)) {
    case 0:
      return this.infinity;
    case 2:
    case 3:
      return null;
    case 4:
    case 6:
    case 7:
      var D = (B.length - 2) / 2;
      var C = B.substr(2, D);
      var A = B.substr(D + 2, D);
      return new ECPointFp(this, this.fromBigInteger(new BigInteger(C, 16)), this.fromBigInteger(new BigInteger(A, 16)));
    default:
      return null
  }
}
ECCurveFp.prototype.getQ = curveFpGetQ;
ECCurveFp.prototype.getA = curveFpGetA;
ECCurveFp.prototype.getB = curveFpGetB;
ECCurveFp.prototype.equals = curveFpEquals;
ECCurveFp.prototype.getInfinity = curveFpGetInfinity;
ECCurveFp.prototype.fromBigInteger = curveFpFromBigInteger;
ECCurveFp.prototype.decodePointHex = curveFpDecodePointHex;
ECFieldElementFp.prototype.getByteLength = function () {
  return Math.floor((this.toBigInteger().bitLength() + 7) / 8)
};
ECPointFp.prototype.getEncoded = function (A) {
  var E = function (F, G) {
    var H = F.toByteArrayUnsigned();
    if (G < H.length) {
      H = H.slice(H.length - G)
    } else {
      while (G > H.length) {
        H.unshift(0)
      }
    }
    return H
  };
  var B = this.getX().toBigInteger();
  var C = this.getY().toBigInteger();
  var D = E(B, 32);
  if (A) {
    if (C.isEven()) {
      D.unshift(2)
    } else {
      D.unshift(3)
    }
  } else {
    D.unshift(4);
    D = D.concat(E(C, 32))
  }
  return D
};
ECPointFp.decodeFrom = function (A, D) {
  var G = D[0];
  var C = D.length - 1;
  var B = D.slice(1, 1 + C / 2);
  var F = D.slice(1 + C / 2, 1 + C);
  B.unshift(0);
  F.unshift(0);
  var E = new BigInteger(B);
  var H = new BigInteger(F);
  return new ECPointFp(A, A.fromBigInteger(E), A.fromBigInteger(H))
};
ECPointFp.decodeFromHex = function (A, D) {
  var G = D.substr(0, 2);
  var C = D.length - 2;
  var B = D.substr(2, C / 2);
  var E = D.substr(2 + C / 2, C / 2);
  var F = new BigInteger(B, 16);
  var H = new BigInteger(E, 16);
  return new ECPointFp(A, A.fromBigInteger(F), A.fromBigInteger(H))
};
ECPointFp.prototype.add2D = function (E) {
  if (this.isInfinity()) {
    return E
  }
  if (E.isInfinity()) {
    return this
  }
  if (this.x.equals(E.x)) {
    if (this.y.equals(E.y)) {
      return this.twice()
    }
    return this.curve.getInfinity()
  }
  var A = E.x.subtract(this.x);
  var B = E.y.subtract(this.y);
  var D = B.divide(A);
  var F = D.square().subtract(this.x).subtract(E.x);
  var C = D.multiply(this.x.subtract(F)).subtract(this.y);
  return new ECPointFp(this.curve, F, C)
};
ECPointFp.prototype.twice2D = function () {
  if (this.isInfinity()) {
    return this
  }
  if (this.y.toBigInteger().signum() == 0) {
    return this.curve.getInfinity()
  }
  var A = this.curve.fromBigInteger(BigInteger.valueOf(2));
  var E = this.curve.fromBigInteger(BigInteger.valueOf(3));
  var B = this.x.square().multiply(E).add(this.curve.a).divide(this.y.multiply(A));
  var C = B.square().subtract(this.x.multiply(A));
  var D = B.multiply(this.x.subtract(C)).subtract(this.y);
  return new ECPointFp(this.curve, C, D)
};
ECPointFp.prototype.multiply2D = function (D) {
  if (this.isInfinity()) {
    return this
  }
  if (D.signum() == 0) {
    return this.curve.getInfinity()
  }
  var A = D;
  var E = A.multiply(new BigInteger("3"));
  var B = this.negate();
  var G = this;
  var F;
  for (F = E.bitLength() - 2; F > 0; F -= 1) {
    G = G.twice();
    var H = E.testBit(F);
    var C = A.testBit(F);
    if (H != C) {
      G = G.add2D(H ? this : B)
    }
  }
  return G
};
ECPointFp.prototype.isOnCurve = function () {
  var D = this.getX().toBigInteger();
  var E = this.getY().toBigInteger();
  var G = this.curve.getA().toBigInteger();
  var F = this.curve.getB().toBigInteger();
  var A = this.curve.getQ();
  var B = E.multiply(E).mod(A);
  var C = D.multiply(D).multiply(D).add(G.multiply(D)).add(F).mod(A);
  return B.equals(C)
};
ECPointFp.prototype.toString = function () {
  return "(" + this.getX().toBigInteger().toString() + "," + this.getY().toBigInteger().toString() + ")"
};
ECPointFp.prototype.validate = function () {
  var A = this.curve.getQ();
  if (this.isInfinity()) {
    throw new Error("Point is at infinity.")
  }
  var B = this.getX().toBigInteger();
  var C = this.getY().toBigInteger();
  if (B.compareTo(BigInteger.ONE) < 0 || B.compareTo(A.subtract(BigInteger.ONE)) > 0) {
    throw new Error("x coordinate out of bounds")
  }
  if (C.compareTo(BigInteger.ONE) < 0 || C.compareTo(A.subtract(BigInteger.ONE)) > 0) {
    throw new Error("y coordinate out of bounds")
  }
  if (!this.isOnCurve()) {
    throw new Error("Point is not on the curve.")
  }
  if (this.multiply(A).isInfinity()) {
    throw new Error("Point is not a scalar multiple of G.")
  }
  return true
};
if (typeof KJUR == "undefined" || !KJUR) {
  KJUR = {}
}
if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) {
  KJUR.crypto = {}
}
KJUR.crypto.ECDSA = function (C) {
  var D = "secp256r1";
  var E = null;
  var G = null;
  var A = null;
  var H = new SecureRandom();
  var F = null;
  this.type = "EC";

  function B(N, J, O, L) {
    var M = Math.max(J.bitLength(), L.bitLength());
    var I = N.add2D(O);
    var S = N.curve.getInfinity();
    for (var K = M - 1; K >= 0; K -= 1) {
      S = S.twice2D();
      S.z = BigInteger.ONE;
      if (J.testBit(K)) {
        if (L.testBit(K)) {
          S = S.add2D(I)
        } else {
          S = S.add2D(N)
        }
      } else {
        if (L.testBit(K)) {
          S = S.add2D(O)
        }
      }
    }
    return S
  }
  this.getBigRandom = function (I) {
    return new BigInteger(I.bitLength(), H).mod(I.subtract(BigInteger.ONE)).add(BigInteger.ONE)
  };
  this.setNamedCurve = function (I) {
    this.ecparams = KJUR.crypto.ECParameterDB.getByName(I);
    this.prvKeyHex = null;
    this.pubKeyHex = null;
    this.curveName = I
  };
  this.setPrivateKeyHex = function (I) {
    this.isPrivate = true;
    this.prvKeyHex = I
  };
  this.setPublicKeyHex = function (I) {
    this.isPublic = true;
    this.pubKeyHex = I
  };
  this.getPublicKeyXYHex = function () {
    var I = this.pubKeyHex;
    if (I.substr(0, 2) !== "04") {
      throw "this method supports uncompressed format(04) only"
    }
    var K = this.ecparams.keylen / 4;
    if (I.length !== 2 + K * 2) {
      throw "malformed public key hex length"
    }
    var J = {};
    J.x = I.substr(2, K);
    J.y = I.substr(2 + K);
    return J
  };
  this.getShortNISTPCurveName = function () {
    var I = this.curveName;
    if (I === "secp256r1" || I === "NIST P-256" || I === "P-256" || I === "prime256v1") {
      return "P-256"
    }
    if (I === "secp384r1" || I === "NIST P-384" || I === "P-384") {
      return "P-384"
    }
    return null
  };
  this.generateKeyPairHex = function () {
    var L = this.ecparams["n"];
    var R = this.getBigRandom(L);
    var Q = this.ecparams["G"].multiply(R);
    var M = Q.getX().toBigInteger();
    var N = Q.getY().toBigInteger();
    var J = this.ecparams["keylen"] / 4;
    var O = ("0000000000" + R.toString(16)).slice(-J);
    var I = ("0000000000" + M.toString(16)).slice(-J);
    var P = ("0000000000" + N.toString(16)).slice(-J);
    var K = "04" + I + P;
    this.setPrivateKeyHex(O);
    this.setPublicKeyHex(K);
    return {
      "ecprvhex": O,
      "ecpubhex": K
    }
  };
  this.signWithMessageHash = function (I) {
    return this.signHex(I, this.prvKeyHex)
  };
  this.signHex = function (K, O) {
    var S = new BigInteger(O, 16);
    var P = this.ecparams["n"];
    var I = new BigInteger(K, 16);
    do {
      var M = this.getBigRandom(P);
      var N = this.ecparams["G"];
      var R = N.multiply(M);
      var L = R.getX().toBigInteger().mod(P)
    } while (L.compareTo(BigInteger.ZERO) <= 0);
    var J = M.modInverse(P).multiply(I.add(S.multiply(L))).mod(P);
    return KJUR.crypto.ECDSA.biRSSigToASN1Sig(L, J)
  };
  this.sign = function (N, I) {
    var S = I;
    var R = this.ecparams["n"];
    var L = BigInteger.fromByteArrayUnsigned(N);
    do {
      var M = this.getBigRandom(R);
      var O = this.ecparams["G"];
      var P = O.multiply(M);
      var K = P.getX().toBigInteger().mod(R)
    } while (K.compareTo(BigInteger.ZERO) <= 0);
    var J = M.modInverse(R).multiply(L.add(S.multiply(K))).mod(R);
    return this.serializeSig(K, J)
  };
  this.verifyWithMessageHash = function (J, I) {
    return this.verifyHex(J, I, this.pubKeyHex)
  };
  this.verifyHex = function (K, M, P) {
    var I, J;
    var N = KJUR.crypto.ECDSA.parseSigHex(M);
    I = N.r;
    J = N.s;
    var O;
    O = ECPointFp.decodeFromHex(this.ecparams["curve"], P);
    var L = new BigInteger(K, 16);
    return this.verifyRaw(L, I, J, O)
  };
  this.verify = function (M, N, L) {
    var I, J;
    if (Bitcoin.Util.isArray(N)) {
      var O = this.parseSig(N);
      I = O.r;
      J = O.s
    } else {
      if ("object" === typeof N && N.r && N.s) {
        I = N.r;
        J = N.s
      } else {
        throw "Invalid value for signature"
      }
    }
    var P;
    if (L instanceof ECPointFp) {
      P = L
    } else {
      if (Bitcoin.Util.isArray(L)) {
        P = ECPointFp.decodeFrom(this.ecparams["curve"], L)
      } else {
        throw "Invalid format for pubkey value, must be byte array or ECPointFp"
      }
    }
    var K = BigInteger.fromByteArrayUnsigned(M);
    return this.verifyRaw(K, I, J, P)
  };
  this.verifyRaw = function (I, K, J, S) {
    var P = this.ecparams["n"];
    var O = this.ecparams["G"];
    if (K.compareTo(BigInteger.ONE) < 0 || K.compareTo(P) >= 0) {
      return false
    }
    if (J.compareTo(BigInteger.ONE) < 0 || J.compareTo(P) >= 0) {
      return false
    }
    var R = J.modInverse(P);
    var M = I.multiply(R).mod(P);
    var T = K.multiply(R).mod(P);
    var N = O.multiply(M).add(S.multiply(T));
    var L = N.getX().toBigInteger().mod(P);
    return L.equals(K)
  };
  this.serializeSig = function (J, K) {
    var L = J.toByteArraySigned();
    var M = K.toByteArraySigned();
    var I = [];
    I.push(2);
    I.push(L.length);
    I = I.concat(L);
    I.push(2);
    I.push(M.length);
    I = I.concat(M);
    I.unshift(I.length);
    I.unshift(48);
    return I
  };
  this.parseSig = function (L) {
    var I;
    if (L[0] != 48) {
      throw new Error("Signature not a valid DERSequence")
    }
    I = 2;
    if (L[I] != 2) {
      throw new Error("First element in signature must be a DERInteger")
    }
    var M = L.slice(I + 2, I + 2 + L[I + 1]);
    I += 2 + L[I + 1];
    if (L[I] != 2) {
      throw new Error("Second element in signature must be a DERInteger")
    }
    var N = L.slice(I + 2, I + 2 + L[I + 1]);
    I += 2 + L[I + 1];
    var J = BigInteger.fromByteArrayUnsigned(M);
    var K = BigInteger.fromByteArrayUnsigned(N);
    return {
      r: J,
      s: K
    }
  };
  this.parseSigCompact = function (M) {
    if (M.length !== 65) {
      throw "Signature has the wrong length"
    }
    var I = M[0] - 27;
    if (I < 0 || I > 7) {
      throw "Invalid signature type"
    }
    var J = this.ecparams["n"];
    var K = BigInteger.fromByteArrayUnsigned(M.slice(1, 33)).mod(J);
    var L = BigInteger.fromByteArrayUnsigned(M.slice(33, 65)).mod(J);
    return {
      r: K,
      s: L,
      i: I
    }
  };
  if (C !== undefined) {
    if (C["curve"] !== undefined) {
      this.curveName = C["curve"]
    }
  }
  if (this.curveName === undefined) {
    this.curveName = D
  }
  this.setNamedCurve(this.curveName);
  if (C !== undefined) {
    if (C["prv"] !== undefined) {
      this.setPrivateKeyHex(C["prv"])
    }
    if (C["pub"] !== undefined) {
      this.setPublicKeyHex(C["pub"])
    }
  }
};
KJUR.crypto.ECDSA.parseSigHex = function (D) {
  var A = KJUR.crypto.ECDSA.parseSigHexInHexRS(D);
  var C = new BigInteger(A.r, 16);
  var B = new BigInteger(A.s, 16);
  return {
    "r": C,
    "s": B
  }
};
KJUR.crypto.ECDSA.parseSigHexInHexRS = function (F) {
  if (F.substr(0, 2) != "30") {
    throw "signature is not a ASN.1 sequence"
  }
  var E = ASN1HEX.getPosArrayOfChildren_AtObj(F, 0);
  if (E.length != 2) {
    throw "number of signature ASN.1 sequence elements seem wrong"
  }
  var B = E[0];
  var D = E[1];
  if (F.substr(B, 2) != "02") {
    throw "1st item of sequene of signature is not ASN.1 integer"
  }
  if (F.substr(D, 2) != "02") {
    throw "2nd item of sequene of signature is not ASN.1 integer"
  }
  var A = ASN1HEX.getHexOfV_AtObj(F, B);
  var C = ASN1HEX.getHexOfV_AtObj(F, D);
  return {
    "r": A,
    "s": C
  }
};
KJUR.crypto.ECDSA.asn1SigToConcatSig = function (A) {
  var C = KJUR.crypto.ECDSA.parseSigHexInHexRS(A);
  var B = C.r;
  var D = C.s;
  if (B.substr(0, 2) == "00" && (((B.length / 2) * 8) % (16 * 8)) == 8) {
    B = B.substr(2)
  }
  if (D.substr(0, 2) == "00" && (((D.length / 2) * 8) % (16 * 8)) == 8) {
    D = D.substr(2)
  }
  if ((((B.length / 2) * 8) % (16 * 8)) != 0) {
    throw "unknown ECDSA sig r length error"
  }
  if ((((D.length / 2) * 8) % (16 * 8)) != 0) {
    throw "unknown ECDSA sig s length error"
  }
  return B + D
};
KJUR.crypto.ECDSA.concatSigToASN1Sig = function (B) {
  if ((((B.length / 2) * 8) % (16 * 8)) != 0) {
    throw "unknown ECDSA concatinated r-s sig  length error"
  }
  var A = B.substr(0, B.length / 2);
  var C = B.substr(B.length / 2);
  return KJUR.crypto.ECDSA.hexRSSigToASN1Sig(A, C)
};
KJUR.crypto.ECDSA.hexRSSigToASN1Sig = function (A, B) {
  var C = new BigInteger(A, 16);
  var D = new BigInteger(B, 16);
  return KJUR.crypto.ECDSA.biRSSigToASN1Sig(C, D)
};
KJUR.crypto.ECDSA.biRSSigToASN1Sig = function (D, E) {
  var A = new KJUR.asn1.DERInteger({
    "bigint": D
  });
  var C = new KJUR.asn1.DERInteger({
    "bigint": E
  });
  var B = new KJUR.asn1.DERSequence({
    "array": [A, C]
  });
  return B.getEncodedHex()
};
(function () {
  var G = CryptoJS;
  var E = G.lib;
  var A = E.WordArray;
  var B = E.Hasher;
  var D = G.algo;
  var F = [];
  var H = D.SM3 = B.extend({
    _doReset: function () {
      this._hash = new A.init([1937774191, 1226093241, 388252375, 3666478592, 2842636476, 372324522, 3817729613, 2969243214])
    },
    _doProcessBlock: function (K, J) {
      var I = this._hash.words;
      var R = I[0];
      var P = I[1];
      var Q = I[2];
      var S = I[3];
      var C = I[4];
      for (var N = 0; N < 80; N += 1) {
        if (N < 16) {
          F[N] = K[J + N] | 0
        } else {
          var O = F[N - 3] ^ F[N - 8] ^ F[N - 14] ^ F[N - 16];
          F[N] = (O << 1) | (O >>> 31)
        }
        var L = ((R << 5) | (R >>> 27)) + C + F[N];
        if (N < 20) {
          L += ((P & Q) | (~P & S)) + 1518500249
        } else {
          if (N < 40) {
            L += (P ^ Q ^ S) + 1859775393
          } else {
            if (N < 60) {
              L += ((P & Q) | (P & S) | (Q & S)) - 1894007588
            } else {
              L += (P ^ Q ^ S) - 899497514
            }
          }
        }
        C = S;
        S = Q;
        Q = (P << 30) | (P >>> 2);
        P = R;
        R = L
      }
      I[0] = (I[0] + R) | 0;
      I[1] = (I[1] + P) | 0;
      I[2] = (I[2] + Q) | 0;
      I[3] = (I[3] + S) | 0;
      I[4] = (I[4] + C) | 0
    },
    _doFinalize: function () {
      var K = this._data;
      var J = K.words;
      var I = this._nDataBytes * 8;
      var C = K.sigBytes * 8;
      J[C >>> 5] |= 128 << (24 - C % 32);
      J[(((C + 64) >>> 9) << 4) + 14] = Math.floor(I / 4294967296);
      J[(((C + 64) >>> 9) << 4) + 15] = I;
      K.sigBytes = J.length * 4;
      this._process();
      return this._hash
    },
    clone: function () {
      var C = B.clone.call(this);
      C._hash = this._hash.clone();
      return C
    }
  });
  G.SM3 = B._createHelper(H);
  G.HmacSM3 = B._createHmacHelper(H)
}());

function SM3Digest() {
  this.BYTE_LENGTH = 64;
  this.xBuf = [];
  this.xBufOff = 0;
  this.byteCount = 0;
  this.DIGEST_LENGTH = 32;
  this.v0 = [1937774191, 1226093241, 388252375, -628488704, -1452330820, 372324522, -477237683, -1325724082];
  this.v = [0, 0, 0, 0, 0, 0, 0, 0];
  this.v_ = [0, 0, 0, 0, 0, 0, 0, 0];
  this.X0 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
  this.X = [68];
  this.xOff = 0;
  this.T_00_15 = 2043430169;
  this.T_16_63 = 2055708042;
  if (arguments.length > 0) {
    this.InitDigest(arguments[0])
  } else {
    this.Init()
  }
}
SM3Digest.prototype = {
  Init: function () {
    this.xBuf = [0, 0, 0, 0];
    this.Reset()
  },
  InitDigest: function (A) {
    this.xBuf = [A.xBuf.length];
    Array.Copy(A.xBuf, 0, this.xBuf, 0, A.xBuf.length);
    this.xBufOff = A.xBufOff;
    this.byteCount = A.byteCount;
    Array.Copy(A.X, 0, this.X, 0, A.X.length);
    this.xOff = A.xOff;
    Array.Copy(A.v, 0, this.v, 0, A.v.length)
  },
  GetDigestSize: function () {
    return this.DIGEST_LENGTH
  },
  Reset: function () {
    this.byteCount = 0;
    this.xBufOff = 0;
    Array.Clear(this.xBuf, 0, this.xBuf.length);
    Array.Copy(this.v0, 0, this.v, 0, this.v0.length);
    this.xOff = 0;
    Array.Copy(this.X0, 0, this.X, 0, this.X0.length)
  },
  GetByteLength: function () {
    return this.BYTE_LENGTH
  },
  ProcessBlock: function () {
    var H;
    var E = this.X;
    var A = [64];
    for (H = 16; H < 68; H += 1) {
      E[H] = this.P1(E[H - 16] ^ E[H - 9] ^ (roateLeft(E[H - 3], 15))) ^ (roateLeft(E[H - 13], 7)) ^ E[H - 6]
    }
    for (H = 0; H < 64; H += 1) {
      A[H] = E[H] ^ E[H + 4]
    }
    var F = this.v;
    var J = this.v_;
    Array.Copy(F, 0, J, 0, this.v0.length);
    var B, C, G, I, D;
    for (H = 0; H < 16; H += 1) {
      D = roateLeft(J[0], 12);
      B = D + J[4] + roateLeft(this.T_00_15, H);
      B = roateLeft(B, 7);
      C = B ^ D;
      G = this.FF_00_15(J[0], J[1], J[2]) + J[3] + C + A[H];
      I = this.GG_00_15(J[4], J[5], J[6]) + J[7] + B + E[H];
      J[3] = J[2];
      J[2] = roateLeft(J[1], 9);
      J[1] = J[0];
      J[0] = G;
      J[7] = J[6];
      J[6] = roateLeft(J[5], 19);
      J[5] = J[4];
      J[4] = this.P0(I)
    }
    for (H = 16; H < 64; H += 1) {
      D = roateLeft(J[0], 12);
      B = D + J[4] + roateLeft(this.T_16_63, H);
      B = roateLeft(B, 7);
      C = B ^ D;
      G = this.FF_16_63(J[0], J[1], J[2]) + J[3] + C + A[H];
      I = this.GG_16_63(J[4], J[5], J[6]) + J[7] + B + E[H];
      J[3] = J[2];
      J[2] = roateLeft(J[1], 9);
      J[1] = J[0];
      J[0] = G;
      J[7] = J[6];
      J[6] = roateLeft(J[5], 19);
      J[5] = J[4];
      J[4] = this.P0(I)
    }
    for (H = 0; H < 8; H += 1) {
      F[H] ^= (J[H])
    }
    this.xOff = 0;
    Array.Copy(this.X0, 0, this.X, 0, this.X0.length)
  },
  ProcessWord: function (B, A) {
    var C = B[A] << 24;
    C |= (B[A += 1] & 255) << 16;
    C |= (B[A += 1] & 255) << 8;
    C |= (B[A += 1] & 255);
    this.X[this.xOff] = C;
    if (++this.xOff == 16) {
      this.ProcessBlock()
    }
  },
  ProcessLength: function (A) {
    if (this.xOff > 14) {
      this.ProcessBlock()
    }
    this.X[14] = (this.URShiftLong(A, 32));
    this.X[15] = (A & (4294967295))
  },
  IntToBigEndian: function (B, C, A) {
    C[A] = (B >>> 24 & 255);
    C[A += 1] = (B >>> 16 & 255);
    C[A += 1] = (B >>> 8 & 255);
    C[A += 1] = (B & 255)
  },
  DoFinal: function (C, A) {
    this.Finish();
    for (var B = 0; B < 8; B += 1) {
      this.IntToBigEndian(this.v[B], C, A + B * 4)
    }
    this.Reset();
    return this.DIGEST_LENGTH
  },
  Update: function (A) {
    this.xBuf[this.xBufOff++] = A;
    if (this.xBufOff == this.xBuf.length) {
      this.ProcessWord(this.xBuf, 0);
      this.xBufOff = 0
    }
    this.byteCount++
  },
  BlockUpdate: function (C, A, B) {
    while ((this.xBufOff != 0) && (B > 0)) {
      this.Update(C[A]);
      A += 1;
      B -= 1
    }
    while (B > this.xBuf.length) {
      this.ProcessWord(C, A);
      A += this.xBuf.length;
      B -= this.xBuf.length;
      this.byteCount += this.xBuf.length
    }
    while (B > 0) {
      this.Update(C[A]);
      A += 1;
      B -= 1
    }
  },
  Finish: function () {
    var A = (this.byteCount << 3);
    this.Update((128));
    while (this.xBufOff != 0) {
      this.Update((0))
    }
    this.ProcessLength(A);
    this.ProcessBlock()
  },
  ROTATE: function (B, A) {
    return (B << A) | (this.URShift(B, (32 - A)))
  },
  P0: function (A) {
    return ((A) ^ roateLeft((A), 9) ^ roateLeft((A), 17))
  },
  P1: function (A) {
    return ((A) ^ roateLeft((A), 15) ^ roateLeft((A), 23))
  },
  FF_00_15: function (B, C, A) {
    return (B ^ C ^ A)
  },
  FF_16_63: function (B, C, A) {
    return ((B & C) | (B & A) | (C & A))
  },
  GG_00_15: function (B, C, A) {
    return (B ^ C ^ A)
  },
  GG_16_63: function (B, C, A) {
    return ((B & C) | (~B & A))
  },
  URShift: function (B, A) {
    console.error(B);
    if (B > Int32.maxValue || B < Int32.minValue) {
      console.error(B);
      B = IntegerParse(B)
    }
    if (B >= 0) {
      return B >> A
    } else {
      return (B >> A) + (2 << ~A)
    }
  },
  URShiftLong: function (A, C) {
    var J;
    var B = new BigInteger();
    B.fromInt(A);
    if (B.signum() >= 0) {
      J = B.shiftRight(C).intValue()
    } else {
      var E = new BigInteger();
      E.fromInt(2);
      var K = ~C;
      var F = "";
      if (K < 0) {
        var I = 64 + K;
        for (var H = 0; H < I; H += 1) {
          F += "0"
        }
        var G = new BigInteger();
        G.fromInt(A >> C);
        var L = new BigInteger("10" + F, 2);
        F = L.toRadix(10);
        var D = L.add(G);
        J = D.toRadix(10)
      } else {
        F = E.shiftLeft((~C)).intValue();
        J = (A >> C) + F
      }
    }
    return J
  },
  GetZ: function (L, B, F) {
    var M = CryptoJS.enc.Utf8.parse(F);
    var J = M.words.length * 4 * 8;
    this.Update((J >> 8 & 255));
    this.Update((J & 255));
    var G = this.GetWords(M.toString());
    this.BlockUpdate(G, 0, G.length);
    var A = this.GetWords(L.curve.a.toBigInteger().toRadix(16));
    var C = this.GetWords(L.curve.b.toBigInteger().toRadix(16));
    var E = this.GetWords(L.getX().toBigInteger().toRadix(16));
    var D = this.GetWords(L.getY().toBigInteger().toRadix(16));
    var I = this.GetWords(B.substr(0, 64));
    var H = this.GetWords(B.substr(64, 64));
    this.BlockUpdate(A, 0, A.length);
    this.BlockUpdate(C, 0, C.length);
    this.BlockUpdate(E, 0, E.length);
    this.BlockUpdate(D, 0, D.length);
    this.BlockUpdate(I, 0, I.length);
    this.BlockUpdate(H, 0, H.length);
    var K = [this.GetDigestSize()];
    this.DoFinal(K, 0);
    return K
  },
  GetWords: function (C) {
    var A = [];
    var D = C.length;
    for (var B = 0; B < D; B += 2) {
      A[A.length] = parseInt(C.substr(B, 2), 16)
    }
    return A
  },
  GetHex: function (D) {
    var A = [];
    var E = 0;
    for (var B = 0; B < D.length * 2; B += 2) {
      A[B >>> 3] |= parseInt(D[E]) << (24 - (B % 8) * 4);
      E += 1
    }
    var C = new CryptoJS.lib.WordArray.init(A, D.length);
    return C
  }
};
Array.Clear = function (A, C, B) {
  for (elm in A) {
    A[elm] = null
  }
};
Array.Copy = function (C, F, A, G, B) {
  var E = C.slice(F, F + B);
  for (var D = 0; D < E.length; D += 1) {
    A[G] = E[D];
    G += 1
  }
};

function roateLeft(A, B) {
  return (A << B) | (A >>> -B)
}
window.Int32 = {
  minValue: -parseInt("10000000000000000000000000000000", 2),
  maxValue: parseInt("1111111111111111111111111111111", 2),
  parse: function (F) {
    if (F < this.minValue) {
      var H = new Number(-F);
      var G = H.toString(2);
      var B = G.substr(G.length - 31, 31);
      var C = "";
      for (var E = 0; E < B.length; E += 1) {
        var D = B.substr(E, 1);
        C += D == "0" ? "1" : "0"
      }
      var A = parseInt(C, 2);
      return (A + 1)
    } else {
      if (F > this.maxValue) {
        var H = Number(F);
        var G = H.toString(2);
        var B = G.substr(G.length - 31, 31);
        var C = "";
        for (var E = 0; E < B.length; E += 1) {
          var D = B.substr(E, 1);
          C += D == "0" ? "1" : "0"
        }
        var A = parseInt(C, 2);
        return -(A + 1)
      } else {
        return F
      }
    }
  },
  parseByte: function (A) {
    if (A > 255) {
      var B = 255 & A;
      return B
    }
    if (A < -256) {
      var B = 255 & A;
      B = 255 ^ B;
      return (B + 1)
    } else {
      return A
    }
  }
};

function IntegerParse(A) {
  if (A > 2147483647 || A < -2147483648) {
    var B = 4294967295 & A;
    if (B > 2147483647) {
      B = 2147483647 & A;
      B = 2147483647 ^ B;
      return -(B + 1)
    }
    return B
  } else {
    return A
  }
}
KJUR.crypto.SM3withSM2 = function (C) {
  var D = "sm2";
  var E = null;
  var G = null;
  var A = null;
  var H = new SecureRandom();
  var F = null;
  this.type = "SM2";

  function B(N, J, O, L) {
    var M = Math.max(J.bitLength(), L.bitLength());
    var I = N.add2D(O);
    var S = N.curve.getInfinity();
    for (var K = M - 1; K >= 0; --K) {
      S = S.twice2D();
      S.z = BigInteger.ONE;
      if (J.testBit(K)) {
        if (L.testBit(K)) {
          S = S.add2D(I)
        } else {
          S = S.add2D(N)
        }
      } else {
        if (L.testBit(K)) {
          S = S.add2D(O)
        }
      }
    }
    return S
  }
  this.getBigRandom = function (I) {
    return new BigInteger(I.bitLength(), H).mod(I.subtract(BigInteger.ONE)).add(BigInteger.ONE)
  };
  this.setNamedCurve = function (I) {
    this.ecparams = KJUR.crypto.ECParameterDB.getByName(I);
    this.prvKeyHex = null;
    this.pubKeyHex = null;
    this.curveName = I
  };
  this.setPrivateKeyHex = function (I) {
    this.isPrivate = true;
    this.prvKeyHex = I
  };
  this.setPublicKeyHex = function (I) {
    this.isPublic = true;
    this.pubKeyHex = I
  };
  this.generateKeyPairHex = function () {
    var L = this.ecparams["n"];
    var R = this.getBigRandom(L);
    var Q = this.ecparams["G"].multiply(R);
    var M = Q.getX().toBigInteger();
    var N = Q.getY().toBigInteger();
    var J = this.ecparams["keylen"] / 4;
    var O = ("0000000000" + R.toString(16)).slice(-J);
    var I = ("0000000000" + M.toString(16)).slice(-J);
    var P = ("0000000000" + N.toString(16)).slice(-J);
    var K = "04" + I + P;
    this.setPrivateKeyHex(O);
    this.setPublicKeyHex(K);
    return {
      "ecprvhex": O,
      "ecpubhex": K
    }
  };
  this.signWithMessageHash = function (I) {
    return this.signHex(I, this.prvKeyHex)
  };
  this.signHex = function (L, R) {
    var X = new BigInteger(R, 16);
    var Q = this.ecparams["n"];
    var I = new BigInteger(L, 16);
    var O = null;
    var S = null;
    var N = null;
    var J = null;
    var V = X;
    do {
      do {
        var M = this.generateKeyPairHex();
        O = new BigInteger(M.ecprvhex, 16);
        var W = M.ecpubhex;
        S = ECPointFp.decodeFromHex(this.ecparams["curve"], W);
        N = I.add(S.getX().toBigInteger());
        N = N.mod(Q)
      } while (N.equals(BigInteger.ZERO) || N.add(O).equals(Q));
      var T = V.add(BigInteger.ONE);
      T = T.modInverse(Q);
      J = N.multiply(V);
      J = O.subtract(J).mod(Q);
      J = T.multiply(J).mod(Q)
    } while (J.equals(BigInteger.ZERO));
    var P = N.toRadix(16);
    var K = J.toRadix(16);
    if (P.length != 64) {
      for (var X = 64 - P.length, U = 0; U < X; U++) {
        P = "0" + P
      }
    }
    if (K.length != 64) {
      for (var X = 64 - K.length, U = 0; U < X; U++) {
        K = "0" + K
      }
    }
    return P + K
  };
  this.sign = function (N, I) {
    var S = I;
    var R = this.ecparams["n"];
    var L = BigInteger.fromByteArrayUnsigned(N);
    do {
      var M = this.getBigRandom(R);
      var O = this.ecparams["G"];
      var P = O.multiply(M);
      var K = P.getX().toBigInteger().mod(R)
    } while (K.compareTo(BigInteger.ZERO) <= 0);
    var J = M.modInverse(R).multiply(L.add(S.multiply(K))).mod(R);
    return this.serializeSig(K, J)
  };
  this.verifyWithMessageHash = function (J, I) {
    return this.verifyHex(J, I, this.pubKeyHex)
  };
  this.verifyHex = function (K, M, R) {
    var I, J;
    I = M.substr(0, 64);
    J = M.substr(64, 64);
    var N = new BigInteger(I, 16);
    var O = new BigInteger(J, 16);
    var P;
    P = ECPointFp.decodeFromHex(this.ecparams["curve"], R);
    var L = new BigInteger(K, 16);
    return this.verifyRaw(L, N, O, P)
  };
  this.verify = function (M, N, L) {
    var I, J;
    if (Bitcoin.Util.isArray(N)) {
      var O = this.parseSig(N);
      I = O.r;
      J = O.s
    } else {
      if ("object" === typeof N && N.r && N.s) {
        I = N.r;
        J = N.s
      } else {
        throw "Invalid value for signature"
      }
    }
    var P;
    if (L instanceof ECPointFp) {
      P = L
    } else {
      if (Bitcoin.Util.isArray(L)) {
        P = ECPointFp.decodeFrom(this.ecparams["curve"], L)
      } else {
        throw "Invalid format for pubkey value, must be byte array or ECPointFp"
      }
    }
    var K = BigInteger.fromByteArrayUnsigned(M);
    return this.verifyRaw(K, I, J, P)
  };
  this.verifyRaw = function (I, K, J, P) {
    var O = this.ecparams["n"];
    var M = this.ecparams["G"];
    var L = K.add(J).mod(O);
    if (L.equals(BigInteger.ZERO)) {
      return false
    }
    if (K.compareTo(BigInteger.ONE) < 0 || K.compareTo(O) >= 0) {
      return false
    }
    if (J.compareTo(BigInteger.ONE) < 0 || J.compareTo(O) >= 0) {
      return false
    }
    if (P.isOnCurve() == 0) {
      return false
    }
    var S = M.multiply(J);
    S = S.add(P.multiply(L));
    var N = I.add(S.getX().toBigInteger()).mod(O);
    return K.equals(N)
  };
  this.serializeSig = function (J, K) {
    var L = J.toByteArraySigned();
    var M = K.toByteArraySigned();
    var I = [];
    I.push(2);
    I.push(L.length);
    I = I.concat(L);
    I.push(2);
    I.push(M.length);
    I = I.concat(M);
    I.unshift(I.length);
    I.unshift(48);
    return I
  };
  this.parseSig = function (L) {
    var I;
    if (L[0] != 48) {
      throw new Error("Signature not a valid DERSequence")
    }
    I = 2;
    if (L[I] != 2) {
      throw new Error("First element in signature must be a DERInteger")
    }
    var M = L.slice(I + 2, I + 2 + L[I + 1]);
    I += 2 + L[I + 1];
    if (L[I] != 2) {
      throw new Error("Second element in signature must be a DERInteger")
    }
    var N = L.slice(I + 2, I + 2 + L[I + 1]);
    I += 2 + L[I + 1];
    var J = BigInteger.fromByteArrayUnsigned(M);
    var K = BigInteger.fromByteArrayUnsigned(N);
    return {
      r: J,
      s: K
    }
  };
  this.parseSigCompact = function (M) {
    if (M.length !== 65) {
      throw "Signature has the wrong length"
    }
    var I = M[0] - 27;
    if (I < 0 || I > 7) {
      throw "Invalid signature type"
    }
    var J = this.ecparams["n"];
    var K = BigInteger.fromByteArrayUnsigned(M.slice(1, 33)).mod(J);
    var L = BigInteger.fromByteArrayUnsigned(M.slice(33, 65)).mod(J);
    return {
      r: K,
      s: L,
      i: I
    }
  };
  if (C !== undefined) {
    if (C["curve"] !== undefined) {
      this.curveName = C["curve"]
    }
  }
  if (this.curveName === undefined) {
    this.curveName = D
  }
  this.setNamedCurve(this.curveName);
  if (C !== undefined) {
    if (C["prv"] !== undefined) {
      this.setPrivateKeyHex(C["prv"])
    }
    if (C["pub"] !== undefined) {
      this.setPublicKeyHex(C["pub"])
    }
  }
};
KJUR.crypto.ECParameterDB = new function () {
  var B = {};
  var C = {};

  function A(D) {
    return new BigInteger(D, 16)
  }
  this.getByName = function (D) {
    var E = D;
    if (typeof C[E] != "undefined") {
      E = C[D]
    }
    if (typeof B[E] != "undefined") {
      return B[E]
    }
    throw "unregistered EC curve name: " + E
  };
  this.regist = function (R, X, Q, K, T, U, I, V, O, W, F, D) {
    B[R] = {};
    var E = A(Q);
    var M = A(K);
    var L = A(T);
    var J = A(U);
    var H = A(I);
    var P = new ECCurveFp(E, M, L);
    var S = P.decodePointHex("04" + V + O);
    B[R]["name"] = R;
    B[R]["keylen"] = X;
    B[R]["curve"] = P;
    B[R]["G"] = S;
    B[R]["n"] = J;
    B[R]["h"] = H;
    B[R]["oid"] = F;
    B[R]["info"] = D;
    for (var N = 0; N < W.length; N += 1) {
      C[W[N]] = R
    }
  }
};
KJUR.crypto.ECParameterDB.regist("secp128r1", 128, "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", "E87579C11079F43DD824993C2CEE5ED3", "FFFFFFFE0000000075A30D1B9038A115", "1", "161FF7528B899B2D0C28607CA52C5B86", "CF5AC8395BAFEB13C02DA292DDED7A83", [], "", "secp128r1 : SECG curve over a 128 bit prime field");
KJUR.crypto.ECParameterDB.regist("secp160k1", 160, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", "0", "7", "0100000000000000000001B8FA16DFAB9ACA16B6B3", "1", "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", "938CF935318FDCED6BC28286531733C3F03C4FEE", [], "", "secp160k1 : SECG curve over a 160 bit prime field");
KJUR.crypto.ECParameterDB.regist("secp160r1", 160, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", "0100000000000000000001F4C8F927AED3CA752257", "1", "4A96B5688EF573284664698968C38BB913CBFC82", "23A628553168947D59DCC912042351377AC5FB32", [], "", "secp160r1 : SECG curve over a 160 bit prime field");
KJUR.crypto.ECParameterDB.regist("secp192k1", 192, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", "0", "3", "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", "1", "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", []);
KJUR.crypto.ECParameterDB.regist("secp192r1", 192, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", "1", "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", []);
KJUR.crypto.ECParameterDB.regist("secp224r1", 224, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", "1", "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", []);
KJUR.crypto.ECParameterDB.regist("secp256k1", 256, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", "0", "7", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", "1", "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", []);
KJUR.crypto.ECParameterDB.regist("secp256r1", 256, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", "1", "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", ["NIST P-256", "P-256", "prime256v1"]);
KJUR.crypto.ECParameterDB.regist("secp384r1", 384, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", "1", "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", "3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", ["NIST P-384", "P-384"]);
KJUR.crypto.ECParameterDB.regist("secp521r1", 521, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", "051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", "1", "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", "011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", ["NIST P-521", "P-521"]);
KJUR.crypto.ECParameterDB.regist("sm2", 256, "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", "1", "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", ["sm2", "SM2"]);

function SM2Cipher(A) {
  this.ct = 1;
  this.p2 = null;
  this.sm3keybase = null;
  this.sm3c3 = null;
  this.key = new Array(32);
  this.keyOff = 0;
  if (typeof (A) != "undefined") {
    this.cipherMode = A
  } else {
    this.cipherMode = SM2CipherMode.C1C3C2
  }
}
SM2Cipher.prototype = {
  getHexString: function (A) {
    if ((A.length & 1) == 0) {
      return A
    } else {
      return "0" + A
    }
  },
  hex2Byte: function (A) {
    if (A > 127 || A < -128) {
      var B = 255 & A;
      if (B > 127) {
        B = 127 & A;
        B = 127 ^ B;
        return -(B + 1)
      }
      return B
    } else {
      return A
    }
  },
  Reset: function () {
    this.sm3keybase = new SM3Digest();
    this.sm3c3 = new SM3Digest();
    var C = this.p2.getX().toBigInteger().toRadix(16);
    var D = this.p2.getY().toBigInteger().toRadix(16);
    if (C.length != 64) {
      for (var A = 64 - C.length, F = 0; F < A; F++) {
        C = "0" + C
      }
    }
    if (D.length != 64 && D.length != 64) {
      A = 64 - D.length;
      for (F = 0; F < A; F++) {
        D = "0" + D
      }
    }
    var B = this.GetWords(C);
    var E = this.GetWords(D);
    this.sm3c3.BlockUpdate(B, 0, B.length);
    this.sm3keybase.BlockUpdate(B, 0, B.length);
    this.sm3keybase.BlockUpdate(E, 0, E.length);
    this.ct = 1;
    this.NextKey()
  },
  NextKey: function () {
    var A = new SM3Digest(this.sm3keybase);
    A.Update(this.ct >> 24 & 255);
    A.Update(this.ct >> 16 & 255);
    A.Update(this.ct >> 8 & 255);
    A.Update(this.ct & 255);
    A.DoFinal(this.key, 0);
    this.keyOff = 0;
    this.ct++
  },
  InitEncipher: function (A) {
    var F = null;
    var E = null;
    var D = new KJUR.crypto.ECDSA({
      "curve": "sm2"
    });
    var B = D.generateKeyPairHex();
    F = new BigInteger(B.ecprvhex, 16);
    var C = B.ecpubhex;
    E = ECPointFp.decodeFromHex(D.ecparams["curve"], C);
    this.p2 = A.multiply(F);
    this.Reset();
    return E
  },
  EncryptBlock: function (B) {
    this.sm3c3.BlockUpdate(B, 0, B.length);
    for (var A = 0; A < B.length; A++) {
      if (this.keyOff == this.key.length) {
        this.NextKey()
      }
      B[A] ^= this.key[this.keyOff++]
    }
  },
  InitDecipher: function (A, B) {
    this.p2 = B.multiply(A);
    this.Reset()
  },
  DecryptBlock: function (B) {
    for (var A = 0; A < B.length; A++) {
      if (this.keyOff == this.key.length) {
        this.NextKey()
      }
      B[A] ^= this.key[this.keyOff++]
    }
    this.sm3c3.BlockUpdate(B, 0, B.length)
  },
  Dofinal: function (B) {
    var C = this.p2.getY().toBigInteger().toRadix(16);
    if (C.length != 64 && C.length != 64) {
      var A = 64 - C.length;
      for (c = 0; c < A; c++) {
        C = "0" + C
      }
    }
    var D = this.GetWords(C);
    this.sm3c3.BlockUpdate(D, 0, D.length);
    this.sm3c3.DoFinal(B, 0);
    this.Reset()
  },
  Encrypt: function (G, E) {
    var B = new Array(E.length);
    Array.Copy(E, 0, B, 0, E.length);
    var A = this.InitEncipher(G);
    this.EncryptBlock(B);
    var F = new Array(32);
    this.Dofinal(F);
    var I;
    var D = A.getX().toBigInteger().toRadix(16);
    var C = A.getY().toBigInteger().toRadix(16);
    if (D.length != 64) {
      for (var J = 64 - D.length, H = 0; H < J; H++) {
        D = "0" + D
      }
    }
    if (C.length != 64 && C.length != 64) {
      J = 64 - C.length;
      for (H = 0; H < J; H++) {
        C = "0" + C
      }
    }
    switch (this.cipherMode) {
      case SM2CipherMode.C1C3C2:
        I = D + C + this.GetHex(F).toString() + this.GetHex(B).toString();
        break;
      case SM2CipherMode.C1C2C3:
        I = A.getX().toBigInteger().toRadix(16) + A.getY().toBigInteger().toRadix(16) + this.GetHex(B).toString() + this.GetHex(F).toString();
        break;
      default:
        throw new Error("[SM2:Decrypt]invalid type cipherMode(" + this.cipherMode + ")")
    }
    return I
  },
  GetWords: function (C) {
    var A = [];
    var D = C.length;
    for (var B = 0; B < D; B += 2) {
      A[A.length] = parseInt(C.substr(B, 2), 16)
    }
    return A
  },
  GetHex: function (D) {
    var A = new Array(32);
    var E = 0;
    for (var B = 0; B < D.length * 2; B += 2) {
      A[B >>> 3] |= parseInt(D[E]) << (24 - (B % 8) * 4);
      E++
    }
    var C = new CryptoJS.lib.WordArray.init(A, D.length);
    return C
  },
  Decrypt: function (O, N) {
    var I = N;
    var H = I.substr(0, 64);
    var G = I.substr(0 + H.length, 64);
    var B;
    var D;
    var L = new KJUR.crypto.ECDSA({
      "curve": "sm2"
    });
    var F = L.ecparams["n"];
    if (O.compareTo(F.subtract(BigInteger.ONE)) > 0) {
      return undefined
    }
    if (O.compareTo(BigInteger.ONE) < 0) {
      return undefined
    }
    switch (this.cipherMode) {
      case SM2CipherMode.C1C3C2:
        D = I.substr(H.length + G.length, 64);
        encrypData = I.substr(H.length + G.length + 64);
        break;
      case SM2CipherMode.C1C2C3:
        encrypData = I.substr(H.length + G.length, I.length - H.length - G.length - 64);
        D = I.substr(I.length - 64);
        break;
      default:
        throw new Error("[SM2:Decrypt]invalid type cipherMode(" + this.cipherMode + ")")
    }
    var E = this.GetWords(encrypData);
    var M = this.CreatePoint(H, G);
    if (M == undefined) {
      return undefined
    }
    this.InitDecipher(O, M);
    this.DecryptBlock(E);
    var K = new Array(32);
    this.Dofinal(K);
    var C = ((this.GetHex(K).toString().toLowerCase()) == (D.toLowerCase()));
    if (C) {
      var J = this.GetHex(E);
      var A = CryptoJS.enc.Utf8.stringify(J);
      return A
    } else {
      throw new Error("[SM2:Decrypt] C3 is not match!");
      return ""
    }
  },
  CreatePoint: function (D, E) {
    var F = new KJUR.crypto.ECDSA({
      "curve": "sm2"
    });
    var C = F.ecparams["curve"];
    var A = "04" + D + E;
    var B = ECPointFp.decodeFromHex(F.ecparams["curve"], A);
    if (B.isOnCurve() == 0) {
      return undefined
    }
    return B
  }
};
window.SM2CipherMode = {
  C1C2C3: 0,
  C1C3C2: 1
};

function SG_sm2Encrypt(D, C) {
  if (D == undefined || C == undefined) {
    return undefined
  }
  if (D == "" || C == "") {
    return undefined
  }
  if (C.length != 130) {
    return undefined
  }
  var E = CryptoJS.enc.Utf8.parse(D);
  var J = C;
  var I = J.substr(0, 2);
  if (I != "04") {
    return undefined
  }
  if (J.length > 64 * 2) {
    J = J.substr(J.length - 64 * 2)
  }
  var B = J.substr(0, 64);
  var F = J.substr(64);
  var A = new SM2Cipher(1);
  var H = A.CreatePoint(B, F);
  if (H == undefined) {
    return undefined
  }
  E = A.GetWords(E.toString());
  var G = A.Encrypt(H, E);
  return "04" + G
}

function SG_sm2Decrypt(B, D) {
  if (B == undefined || D == undefined) {
    return undefined
  }
  if (B == "" || D == "") {
    return undefined
  }
  if (D.length != 64) {
    return undefined
  }
  if (B.length <= 194) {
    return undefined
  }
  var F = B.substr(0, 2);
  if (F != "04") {
    return undefined
  }
  B = B.substr(2);
  var E = new BigInteger(D, 16);
  var C = new SM2Cipher(1);
  var A = C.Decrypt(E, B);
  return A
}

function SG_sm3encrypt(E) {
  if (E == undefined) {
    return undefined
  }
  if (E == "") {
    return undefined
  }
  var A = CryptoJS.enc.Utf8.parse(E);
  var C = new SM3Digest();
  A = C.GetWords(A.toString());
  C.BlockUpdate(A, 0, A.length);
  var D = new Array(32);
  C.DoFinal(D, 0);
  var B = C.GetHex(D).toString();
  return B
}

function SG_sm2generateKeyPair() {
  var A = new KJUR.crypto.ECDSA({
    "curve": "SM2"
  });
  return A.generateKeyPairHex()
}

function generateSM4Key() {
  var R = new SecureRandom();
  var A = new Array(16);
  R.nextBytes(A);
  var D = new SM3Digest().GetHex(A);
  return D.toString()
};
/**
 * sm4加密(只支持CBC加密方式)
 * 使用方式如下：
 *  	var sm4=new SM4();
 * 		m4.encrypt_cbc(data,key,iv);
 * 		sm4.decrypt_cbc(data,key,iv);
 */
function SM4() {
  this.sbox = new Array(0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8, 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f, 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48);
  this.fk = new Array(0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc);
  this.ck = new Array(0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279)
};
SM4.prototype = {
  expandKey: function (key) {
    var k = new Array(36);
    var mk = byteArrayToIntArray(key);
    k[0] = mk[0] ^ this.fk[0];
    k[1] = mk[1] ^ this.fk[1];
    k[2] = mk[2] ^ this.fk[2];
    k[3] = mk[3] ^ this.fk[3];
    var rk = new Array(32);
    for (var i = 0; i < 32; i++) {
      k[(i + 4)] = (k[i] ^ this.T1(k[(i + 1)] ^ k[(i + 2)] ^ k[(i + 3)] ^ this.ck[i]));
      rk[i] = k[(i + 4)]
    }
    return rk
  },
  T1: function (ta) {
    var rk = 0;
    var b = new Array(4);
    var a = intToByte(ta);
    b[0] = this.sbox[a[0] & 0xFF];
    b[1] = this.sbox[a[1] & 0xFF];
    b[2] = this.sbox[a[2] & 0xFF];
    b[3] = this.sbox[a[3] & 0xFF];
    var bint = byteToInt(b, 0);
    var rk = bint ^ (bint << 13 | (bint >>> (32 - 13))) ^ (bint << 23 | (bint >>> (32 - 23)));
    return rk
  },
  one_encrypt: function (rk, data) {
    var x = new Array(36);
    x[0] = byteToInt(data, 0);
    x[1] = byteToInt(data, 4);
    x[2] = byteToInt(data, 8);
    x[3] = byteToInt(data, 12);
    for (var i = 0; i < 32; i++) {
      x[(i + 4)] = x[i] ^ this.T0(x[(i + 1)] ^ x[(i + 2)] ^ x[(i + 3)] ^ rk[i])
    };
    var tmpx = new Array(4);
    for (var i = 35; i >= 32; i--) {
      tmpx[35 - i] = x[i]
    };
    var xbyte = intArrayToByteArray(tmpx);
    return xbyte
  },
  T0: function (ta) {
    var a = intToByte(ta);
    var b = new Array(4);
    b[0] = this.sbox[a[0] & 0xFF];
    b[1] = this.sbox[a[1] & 0xFF];
    b[2] = this.sbox[a[2] & 0xFF];
    b[3] = this.sbox[a[3] & 0xFF];
    var bint = byteToInt(b, 0);
    var c = bint ^ (bint << 2 | (bint >>> (32 - 2))) ^ (bint << 10 | (bint >>> (32 - 10))) ^ (bint << 18 | (bint >>> (32 - 18))) ^ (bint << 24 | (bint >>> (32 - 24)));
    return c
  },
  pkcs7padding: function (input, mode) {
    if (input == null) {
      return null
    }
    var ret = null;
    if (mode == 1) {
      var p = 16 - input.length % 16;
      ret = new Array(input.length + p);
      arrayCopy(input, 0, ret, 0, input.length);
      for (var i = 0; i < p; i++) {
        ret[input.length + i] = 0
      }
    } else {
      var p = input[input.length - 1];
      ret = new Array(input.length - p);
      arrayCopy(input, 0, ret, 0, input.length - p)
    }
    return ret
  },
  encrypt_cbc: function (data, key, iv) {
    if (key == undefined || key == null || key.length % 16 != 0) {
      console.log("sm4 key is error!");
      return null
    }
    if (data == undefined || data == null || data.length <= 0) {
      console.log("data is error!");
      return null
    }
    if (iv == undefined || iv == null || iv.length % 16 != 0) {
      console.log("iv is error!");
      return null
    }
    key = Hex.decode(key);
    iv = Hex.decode(iv);
    data = Hex.utf8StrToBytes(data);
    var rk = this.expandKey(key);
    var blockLen = 16;
    var loop = parseInt(data.length / blockLen);
    var cipher = new Array((loop + 1) * blockLen);
    var tmp = new Array(blockLen);
    var oneCipher = null;
    for (var i = 0; i < loop; i++) {
      arrayCopy(data, i * blockLen, tmp, 0, blockLen);
      for (var j = 0; j < blockLen; j++) {
        tmp[j] = tmp[j] ^ iv[j]
      };
      iv = this.one_encrypt(rk, tmp);
      arrayCopy(iv, 0, cipher, i * blockLen, blockLen)
    };
    var lessData = new Array(data.length % blockLen);
    if (lessData.length > 0) {
      arrayCopy(data, loop * blockLen, lessData, 0, data.length % blockLen)
    }
    var padding = this.pkcs7padding(lessData, 1);
    for (var i = 0; i < blockLen; i++) {
      padding[i] = padding[i] ^ iv[i]
    }
    iv = this.one_encrypt(rk, padding);
    arrayCopy(iv, 0, cipher, loop * blockLen, blockLen);
    return Hex.encode(cipher, 0, cipher.length)
  },
  decrypt_cbc: function (data, key, iv) {
    if (key == undefined || key == null || key.length % 16 != 0) {
      console.log("sm4 key is error!");
      return null
    }
    if (data == undefined || data == null || data.length % 16 != 0) {
      console.log("data is error!");
      return null
    }
    if (iv == undefined || iv == null || iv.length % 16 != 0) {
      console.log("iv is error!");
      return null
    }
    key = Hex.decode(key);
    iv = Hex.decode(iv);
    data = Hex.decode(data);
    var rk = this.expandKey(key);
    var nrk = new Array(32);
    for (var i = 0; i < rk.length; i++) {
      nrk[i] = rk[32 - i - 1]
    };
    var blockLen = 16;
    var loop = data.length / blockLen;
    var tmp = new Array(blockLen);
    var onePlain = null;
    var plain = null;
    plain = new Array(data.length);
    for (var i = 0; i < loop; i++) {
      arrayCopy(data, i * blockLen, tmp, 0, blockLen);
      onePlain = this.one_encrypt(nrk, tmp);
      for (var j = 0; j < blockLen; j++) {
        onePlain[j] = onePlain[j] ^ iv[j]
      };
      arrayCopy(tmp, 0, iv, 0, blockLen);
      arrayCopy(onePlain, 0, plain, i * blockLen, blockLen)
    };
    var lastPart = this.pkcs7padding(onePlain, 1);
    var realPlain = new Array(plain.length - blockLen + lastPart.length);
    arrayCopy(plain, 0, realPlain, 0, plain.length - blockLen);
    arrayCopy(lastPart, 0, realPlain, plain.length - blockLen, lastPart.length);
    realPlain = realPlain.filter(function (x) {
      return x != 0
    });
    return Hex.bytesToUtf8Str(realPlain)
  }
};
var SecureRandom = function () {
  function G(J) {
    D[F++] ^= J & 255;
    D[F++] ^= J >> 8 & 255;
    D[F++] ^= J >> 16 & 255;
    D[F++] ^= J >> 24 & 255;
    F >= A && (F -= A)
  }
  var I, D, F, A = 256;
  if (D == null) {
    D = [];
    F = 0;
    var E;
    for (; F < A;) {
      E = Math.floor(window.crypto.getRandomValues(new Uint16Array(1))[0]), D[F++] = E >>> 8, D[F++] = E & 255
    };
    if (myBrowser() == "FF" && window.crypto) {
      var C = new ArrayBuffer(32);
      var H = new Int8Array(C);
      window.crypto.getRandomValues(H);
      for (E = 0; E < H.length; ++E) {
        D[E] = H[E] & 255
      }
    } else {
      if (myBrowser() == "IE11") {
        var C = new ArrayBuffer(32);
        var H = new Int8Array(C);
        var B = window.crypto || window.msCrypto;
        B.getRandomValues(H);
        for (E = 0; E < H.length; ++E) {
          D[E] = H[E] & 255
        }
      } else {
        if (myBrowser() == "edge") {
          var C = new ArrayBuffer(32);
          var H = new Int8Array(C);
          var B = window.crypto || window.msCrypto;
          B.getRandomValues(H);
          for (E = 0; E < H.length; ++E) {
            D[E] = H[E] & 255
          }
        } else {}
      }
    }
    F = 0;
    G((new Date).getTime())
  }
  this.nextBytes = function (L) {
    for (var N = 0; N < L.length; ++N) {
      var J = L,
        K = N,
        M;
      if (I == null) {
        G((new Date).getTime());
        I = new prng_newstate;
        I.init(D);
        for (F = 0; F < D.length; ++F) {
          D[F] = 0
        }
        F = 0
      }
      M = I.next();
      J[K] = M
    }
  }
};

function myBrowser() {
  var D = navigator.userAgent;
  var F = D.indexOf("Opera") > -1;
  var B = D.indexOf("compatible") > -1 && D.indexOf("MSIE") > -1;
  var E = D.indexOf("Edge") > -1 && !B;
  var C = D.indexOf("Trident") > -1 && D.indexOf("rv:11.0") > -1;
  var H = D.indexOf("Firefox") > -1;
  var A = D.indexOf("Safari") > -1;
  var G = D.indexOf("Chrome") > -1;
  if (E) {
    return "edge"
  }
  if (C) {
    return "IE11"
  }
  if (H) {
    return "FF"
  }
  if (G) {
    return "FF"
  }
};

function prng_newstate() {
  this.j = this.i = 0;
  this.S = [];
  this.init = function (A) {
    for (var B, C, D = 0; D < 256; ++D) {
      this.S[D] = D
    };
    for (D = B = 0; D < 256; ++D) {
      B = B + this.S[D] + A[D % A.length] & 255, C = this.S[D], this.S[D] = this.S[B], this.S[B] = C
    };
    this.j = this.i = 0
  };
  this.next = function () {
    var A;
    this.i = this.i + 1 & 255;
    this.j = this.j + this.S[this.i] & 255;
    A = this.S[this.i];
    this.S[this.i] = this.S[this.j];
    this.S[this.j] = A;
    return this.S[A + this.S[this.i] & 255]
  }
};
Array.Clear = function (A) {
  for (elm in A) {
    A[elm] = null
  }
};
Array.Copy = function (B, A, D, C, E) {
  B = B.slice(A, A + E);
  for (A = 0; A < B.length; A++) {
    D[C] = B[A], C++
  }
};

function arrayCopy(src, pos1, dest, pos2, len) {
  var realLen = len;
  if (pos1 + len > src.length && pos2 + len <= dest.length) {
    realLen = src.length - pos1
  } else if (pos2 + len > dest.length && pos1 + len <= src.length) {
    realLen = dest.length - pos2
  } else if (pos1 + len <= src.length && pos2 + len <= dest.length) {
    realLen = len
  } else if (dest.length < src.length) {
    realLen = dest.length - pos2
  } else {
    realLen = src.length - pos2
  }
  for (var i = 0; i < realLen; i++) {
    dest[i + pos2] = src[i + pos1]
  }
}

function longToByte(num) {
  return new Array(0, 0, 0, 0, (num >> 24) & 0x000000FF, (num >> 16) & 0x000000FF, (num >> 8) & 0x000000FF, (num) & 0x000000FF)
}

function intToByte(num) {
  return new Array((num >> 24) & 0x000000FF, (num >> 16) & 0x000000FF, (num >> 8) & 0x000000FF, (num) & 0x000000FF)
}

function intArrayToByteArray(nums) {
  var b = new Array(nums.length * 4);
  for (var i = 0; i < nums.length; i++) {
    arrayCopy(intToByte(nums[i]), 0, b, i * 4, 4)
  }
  return b
}

function byteToInt(b, pos) {
  if (pos + 3 < b.length) {
    return ((b[pos]) << 24) | ((b[pos + 1]) << 16) | ((b[pos + 2]) << 8) | ((b[pos + 3]))
  } else if (pos + 2 < b.length) {
    return ((b[pos + 1]) << 16) | ((b[pos + 2]) << 8) | ((b[pos + 3]))
  } else if (pos + 1 < b.length) {
    return ((b[pos]) << 8) | ((b[pos + 1]))
  } else {
    return ((b[pos]))
  }
}

function byteArrayToIntArray(b) {
  var arrLen = Math.ceil(b.length / 4);
  var out = new Array(arrLen);
  for (var i = 0; i < b.length; i++) {
    b[i] = b[i] & 0xFF
  }
  for (var i = 0; i < out.length; i++) {
    out[i] = byteToInt(b, i * 4)
  }
  return out
};

function Hex() {};
Hex.encode = function (b, pos, len) {
  var hexCh = new Array(len * 2);
  var hexCode = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
  for (var i = pos, j = 0; i < len + pos; i++, j++) {
    hexCh[j] = hexCode[(b[i] & 0xFF) >> 4];
    hexCh[++j] = hexCode[(b[i] & 0x0F)]
  }
  return hexCh.join('')
};
Hex.decode = function (hex) {
  if (hex == null || hex == '') {
    return null
  }
  if (hex.length % 2 != 0) {
    return null
  }
  var ascLen = hex.length / 2;
  var hexCh = this.toCharCodeArray(hex);
  var asc = new Array(ascLen);
  for (var i = 0; i < ascLen; i++) {
    if (hexCh[2 * i] >= 0x30 && hexCh[2 * i] <= 0x39) {
      asc[i] = ((hexCh[2 * i] - 0x30) << 4)
    } else if (hexCh[2 * i] >= 0x41 && hexCh[2 * i] <= 0x46) {
      asc[i] = ((hexCh[2 * i] - 0x41 + 10) << 4)
    } else if (hexCh[2 * i] >= 0x61 && hexCh[2 * i] <= 0x66) {
      asc[i] = ((hexCh[2 * i] - 0x61 + 10) << 4)
    } else {
      return null
    }
    if (hexCh[2 * i + 1] >= 0x30 && hexCh[2 * i + 1] <= 0x39) {
      asc[i] = (asc[i] | (hexCh[2 * i + 1] - 0x30))
    } else if (hexCh[2 * i + 1] >= 0x41 && hexCh[2 * i + 1] <= 0x46) {
      asc[i] = (asc[i] | (hexCh[2 * i + 1] - 0x41 + 10))
    } else if (hexCh[2 * i + 1] >= 0x61 && hexCh[2 * i + 1] <= 0x66) {
      asc[i] = (asc[i] | (hexCh[2 * i + 1] - 0x61 + 10))
    } else {
      return null
    }
  }
  return asc
};
Hex.utf8StrToHex = function (utf8Str) {
  var ens = encodeURIComponent(utf8Str);
  var es = unescape(ens);
  var esLen = es.length;
  var words = [];
  for (var i = 0; i < esLen; i++) {
    words[i] = (es.charCodeAt(i).toString(16))
  }
  return words.join('')
};
Hex.utf8StrToBytes = function (utf8Str) {
  var ens = encodeURIComponent(utf8Str);
  var es = unescape(ens);
  var esLen = es.length;
  var words = [];
  for (var i = 0; i < esLen; i++) {
    words[i] = es.charCodeAt(i)
  }
  return words
};
Hex.hexToUtf8Str = function (utf8Str) {
  var utf8Byte = Hex.decode(utf8Str);
  var latin1Chars = [];
  for (var i = 0; i < utf8Byte.length; i++) {
    latin1Chars.push(String.fromCharCode(utf8Byte[i]))
  }
  return decodeURIComponent(escape(latin1Chars.join('')))
};
Hex.bytesToUtf8Str = function (bytesArray) {
  var utf8Byte = bytesArray;
  var latin1Chars = [];
  for (var i = 0; i < utf8Byte.length; i++) {
    latin1Chars.push(String.fromCharCode(utf8Byte[i]))
  }
  return decodeURIComponent(escape(latin1Chars.join('')))
};
Hex.toCharCodeArray = function (chs) {
  var chArr = new Array(chs.length);
  for (var i = 0; i < chs.length; i++) {
    chArr[i] = chs.charCodeAt(i)
  };
  return chArr
};
